0-আকারের গতিশীল অ্যারেতে পয়েন্টার বাড়ানো কি সংজ্ঞায়িত?


34

আফাইক, যদিও আমরা 0-আকারের স্ট্যাটিক-মেমরি অ্যারে তৈরি করতে পারি না, তবে আমরা গতিশীলগুলির সাথে এটি করতে পারি:

int a[0]{}; // Compile-time error
int* p = new int[0]; // Is well-defined

আমি যেমন পড়েছি, pএক অতীত-শেষের উপাদানটির মতো কাজ করে। আমি যে ঠিকানাটি pনির্দেশ করে তা মুদ্রণ করতে পারি ।

if(p)
    cout << p << endl;
  • যদিও আমি নিশ্চিত যে আমরা পুনরাবৃত্তকারী (অতীত-শেষ উপাদান) এর সাথে পারি না বলে আমরা সেই পয়েন্টারটিকে (অতীত-শেষ-উপাদান) অবহেলা করতে পারি না তবে আমি কীসের বিষয়ে নিশ্চিত নই সেই পয়েন্টারটি বাড়ানো কিনা p? একটি অপরিবর্তিত আচরণ (ইউবি) কি পুনরাবৃত্তকারীদের মতো?

    p++; // UB?

4
ইউবি "... অন্য কোনও পরিস্থিতি (যা একই পয়েন্টারটি একই অ্যারের উপাদান বা শেষের দিকে একের দিকে নির্দেশ করছে না এমন পয়েন্টার উত্পন্ন করার চেষ্টা করছে) অপরিজ্ঞাত
ডাব্লু

3
ভাল, এটি এর std::vectorসাথে 0 টি আইটেমের সাথে মিল । begin()ইতিমধ্যে সমান end()তাই আপনি প্রারম্ভের দিকে ইঙ্গিতকারী একটি পুনরাবৃত্তি বৃদ্ধি করতে পারবেন না।
ফিল 1970

1
@ পিটারমোরটেনসেন আমি মনে করি আপনার সম্পাদনাটি শেষ বাক্যটির অর্থ পরিবর্তন করেছে ("আমি নিশ্চিত যে -> আমি কেন নিশ্চিত নই"), আপনি কি দয়া করে ডাবল চেক করতে পারবেন?
ফ্যাবিও মনিকাকে

@ পিটারমোরটেনসেন: আপনি সম্পাদিত শেষ অনুচ্ছেদটি কিছুটা কম পঠনযোগ্য হয়ে উঠেছে।
Itachi Uchiwa

উত্তর:


32

অ্যারের উপাদানগুলিকে পয়েন্টারগুলিকে একটি বৈধ উপাদান বা শেষের একটিতে চিহ্নিত করার অনুমতি দেওয়া হয়। যদি আপনি এমনভাবে পয়েন্টারটি বৃদ্ধি করেন যা শেষের চেয়ে একেরও বেশি সময় ধরে যায়, তবে আচরণটি অপরিবর্তিত।

আপনার 0-আকারের অ্যারের জন্য, p ইতিমধ্যে শেষের দিকে একটি ইতিমধ্যে নির্দেশ করছে, সুতরাং এটি বাড়ানো অনুমোদিত নয়।

+অপারেটর সম্পর্কিত সি ++ 17 8.7 / 4 দেখুন ( ++একই বিধিনিষেধ রয়েছে):

চ অভিব্যক্তি Pউপাদানে পয়েন্ট x[i]একটি অ্যারের বস্তুর xএন উপাদান, এক্সপ্রেশন সঙ্গে P + JএবংJ + P (যেখানে Jমূল্য আছে j) বিন্দু (সম্ভবত-প্রকল্পিত) উপাদানে x[i+j]যদি 0≤i + + j≤n; অন্যথায়, আচরণটি সংজ্ঞায়িত।


2
সুতরাং একমাত্র ক্ষেত্রে x[i]একই x[i + j]হয় যখন উভয় iএবং jমান 0 হয়?
রামি ইয়েন

8
@RamiYen x[i]হিসাবে একই উপাদান x[i+j]যদি j==0
ইন্টারজয়

1
ওহ, আমি সি ++ শব্দার্থবিজ্ঞানের "গোধূলি অঞ্চল" ঘৃণা করি ... যদিও +1।
einpoklum

4
@ আইনপোক্লাম-রিস্টেস্টমোনিকা: কোনও গোধূলি অঞ্চল নেই really এটি কেবল সি ++ এমনকি এন = 0 ক্ষেত্রেও সামঞ্জস্যপূর্ণ। এন উপাদানগুলির একটি অ্যারের জন্য, এন + 1 টি বৈধ পয়েন্টার মান রয়েছে কারণ আপনি অ্যারের পিছনে নির্দেশ করতে পারেন। তার মানে আপনি অ্যারের শুরুতে শুরু করতে পারেন এবং শেষ দিকে পেতে পয়েন্টার এন বার বৃদ্ধি করতে পারেন।
এমসাল্টারস

1
@ ম্যাক্সিম এগারোশকিন আমার উত্তরটি বর্তমানে ভাষাটি কী অনুমতি দেয় তা সম্পর্কে। আপনার বিষয়ে আলোচনাটি এটির পরিবর্তে বিষয় ছাড়াই অনুমোদিত হতে চাইবে।
ইন্টারজয়

2

আমার ধারণা আপনার কাছে ইতিমধ্যে উত্তরটি আছে; আপনি যদি কিছুটা গভীর দেখেন: আপনি বলেছিলেন যে অফ-দ্য-এ-এডেটর বাড়ানো এইভাবে ইউবি হয়: এই উত্তরটি একটি পুনরাবৃত্তিকে কী বলে?

পুনরুক্তিকারী কেবলমাত্র একটি অবজেক্ট যার একটি পয়েন্টার রয়েছে এবং এটির পয়েন্টারটি সত্যিকার অর্থে পয়েন্টারটি বাড়িয়ে দিচ্ছে। সুতরাং অনেক ক্ষেত্রে একটি পয়েন্টারের শর্তে একটি পুনরাবৃত্তিকে পরিচালনা করা হয়।

int arr [] = {0,1,2,3,4,5,6,7,8,9};

int * p = arr; // পি আরআর প্রথম উপাদানকে নির্দেশ করে

++, পি; // পি আরআর পয়েন্ট [1]

আমরা যেমন কোনও ভেক্টরের উপাদানগুলিকে অবিচ্ছিন্ন করতে পুনরাবৃত্তকারী ব্যবহার করতে পারি, তেমনি আমরা অ্যারেতে উপাদানগুলি অতিক্রম করতে পয়েন্টার ব্যবহার করতে পারি। অবশ্যই, এটি করার জন্য আমাদের সর্বশেষ উপাদানটির প্রথম এবং একটিতে পয়েন্টার অর্জন করতে হবে। যেমনটি আমরা সবেমাত্র দেখেছি, অ্যারে নিজেই ব্যবহার করে বা প্রথম উপাদানটির ঠিকানা গ্রহণ করে আমরা প্রথম উপাদানটির জন্য একটি পয়েন্টার পেতে পারি। অ্যারেগুলির অন্য একটি বিশেষ সম্পত্তি ব্যবহার করে আমরা একটি অফ-দ্য-এ-পয়েন্টার পেতে পারি। একটি অ্যারের শেষ উপাদানটির একের আগে আমরা অস্তিত্বের উপাদানটির ঠিকানা নিতে পারি:

ইন্ট * ই = & আরআর [10]; // পয়েন্টারটি আরারের শেষ উপাদানটি পেরিয়ে গেছে

এখানে আমরা সাবস্ক্রিপ্ট অপারেটরটি একটি অজানা উপাদানকে সূচক হিসাবে ব্যবহার করেছি; অ্যারের দশটি উপাদান রয়েছে, সুতরাং আর্টের সর্বশেষ উপাদানটি সূচী অবস্থানে রয়েছে 9. কেবলমাত্র এই উপাদানটি আমরা করতে পারি এটির ঠিকানা নেওয়া যা আমরা ই শুরু করতে পারি। অফ-দ্য-এ-এডিটর (§ 3.4.1, পি। 106) এর মতো একটি অফ-দ্য-ইন্ড পয়েন্টার কোনও উপাদানকে নির্দেশ করে না। ফলস্বরূপ, আমরা কোনও অফ-দ্য-ইন্ড পয়েন্টারকে অবচয় বা বাড়িয়ে তুলতে পারি না।

এটি লিপম্যানের সি ++ প্রাইমার 5 সংস্করণ থেকে।

সুতরাং এটি ইউবি এটি করবেন না।


-4

কঠোর অর্থে, এটি সংজ্ঞায়িত আচরণ নয়, তবে বাস্তবায়ন-সংজ্ঞায়িত। সুতরাং, যদিও অজ্ঞ যদি অ মূলধারার আর্কিটেকচারের সমর্থন করার জন্য পরিকল্পনা, আপনি করতে পারেন সম্ভবত এটা করতে।

ইন্টারজয়ের দেওয়া মানক উক্তিটি একটি ভাল, এটি ইউবি নির্দেশ করে, তবে এটি আমার মতে দ্বিতীয়টি সেরা হিট, যেহেতু এটি পয়েন্টার-পয়েন্টার গাণিতিক নিয়ে কাজ করে (মজাদারভাবে, একটি স্পষ্টতই ইউবি, অন্যটি হয় না)। প্রশ্নটিতে অপারেশন নিয়ে সরাসরি কাজ করার একটি অনুচ্ছেদ রয়েছে:

[expr.post.incr] / [expr.pre.incr]
অপারেন্ডটি হতে হবে [...] বা সম্পূর্ণ সংজ্ঞায়িত অবজেক্ট টাইপের পয়েন্টার।

ওহ, একটি মুহুর্ত অপেক্ষা করুন, একটি সম্পূর্ণ সংজ্ঞায়িত অবজেক্টের ধরণ? এখানেই শেষ? আমি বলতে চাইছি, সত্যিই, টাইপ করুন ? সুতরাং আপনি কোন জিনিস প্রয়োজন হয় না?
এটি পড়ার জন্য বেশ খানিকটা সময় লাগে আসলে একটি ইঙ্গিতটি খুঁজে পাওয়া যায় যে সেখানকার কিছু সম্ভবত খুব ভাল সংজ্ঞায়িত নাও হতে পারে। কারণ এখনও অবধি, এটি এমনভাবে পড়ে যে আপনি একে একে একে পুরোপুরি অনুমতি দিচ্ছেন, কোনও বিধিনিষেধ নেই।

[basic.compound] 3একজনের কী ধরণের পয়েন্টার থাকতে পারে সে সম্পর্কে একটি বিবৃতি দেয় এবং অন্য তিনটির মধ্যে কেউ না হওয়ায় আপনার ক্রিয়াকলাপের ফলাফলটি স্পষ্টভাবে ৩.৪ এর আওতায় পড়বে: অবৈধ পয়েন্টার
তবে এটি এটি বলে না যে আপনাকে একটি অবৈধ পয়েন্টার রাখার অনুমতি নেই। বিপরীতে, এটি কিছু খুব সাধারণ, সাধারণ অবস্থার তালিকা (যেমন সঞ্চয়স্থানের সময়সীমা) যেখানে পয়েন্টারগুলি নিয়মিতভাবে অবৈধ হয়ে যায়। সুতরাং এটি সম্ভবত একটি অনুমোদিত জিনিস। এবং প্রকৃতপক্ষে:

[বেসেল.এসসিসি] 4
একটি অবৈধ পয়েন্টার মানের মাধ্যমে ইন্ডিরেশন এবং একটি অবৈধ পয়েন্টার মানকে একটি নির্ধারণের ফাংশনে পাস করার অপরিবর্তিত আচরণ রয়েছে। একটি অবৈধ পয়েন্টার মানের অন্য কোনও ব্যবহারের প্রয়োগ-সংজ্ঞায়িত আচরণ রয়েছে।

আমরা সেখানে একটি "অন্য কোনও" করছি, সুতরাং এটি সংজ্ঞায়িত আচরণ নয়, তবে বাস্তবায়ন-সংজ্ঞায়িত, সুতরাং সাধারণত অনুমোদিত (যেমন বাস্তবায়ন স্পষ্টভাবে কিছু আলাদাভাবে না বলে)।

দুর্ভাগ্যক্রমে, এটি গল্পের শেষ নয়। যদিও নেট ফলাফলটি এখান থেকে আর কোনও পরিবর্তন হয় না, এটি আরও বিভ্রান্তিকর হয়ে ওঠে, আপনি যতক্ষণ "পয়েন্টার" সন্ধান করেন:

[মৌলিক.কম্পাউন্ড]
কোনও অবজেক্ট পয়েন্টার টাইপের একটি বৈধ মান মেমরির কোনও বাইটের ঠিকানা বা নাল পয়েন্টারটিকে প্রতিনিধিত্ব করে। টি টাইপের কোনও বস্তু যদি কোনও ঠিকানার এ অবস্থিত হয় তবে [...] মানটি কীভাবে প্রাপ্ত হয়েছিল তা বিবেচনা না করেই সেই অবজেক্টের দিকে নির্দেশ করতে বলা হয় ।
[দ্রষ্টব্য: উদাহরণস্বরূপ, অ্যারের শেষের পূর্বের ঠিকানাটি ঠিকানায় অবস্থিত অ্যারের উপাদান ধরণের কোনও সম্পর্কযুক্ত অবজেক্টের দিকে নির্দেশ করে বিবেচনা করা হবে। [...]]।

হিসাবে পড়ুন: ঠিক আছে, কে যত্নশীল! স্মৃতিতে কোথাও পয়েন্টার পয়েন্ট করা পর্যন্ত আমি ভাল আছি?

[বেসরাল.এসটিসি.ডিনামিক.স্যাফটি] একটি পয়েন্টার মান হ'ল নিরাপদে উত্পন্ন পয়েন্টার [ব্লাহ ব্লাহ]

হিসাবে পড়ুন: ঠিক আছে, নিরাপদে প্রাপ্ত, যাই হোক না কেন। এটি কী তা ব্যাখ্যা করে না, বা এটি বলে না যে আসলে আমার এটির প্রয়োজন ছিল। নিরাপদে-ডিরাইভড-নরক। স্পষ্টতই আমি এখনও নিরাপদ থেকে প্রাপ্ত-পয়েন্টারগুলি ঠিক ঠিক রাখতে পারি। আমি অনুমান করছি যে তাদেরকে ডিফারেন্স করা সম্ভবত এতো ভাল ধারণা হবে না তবে এগুলি রাখার পক্ষে এটি পুরোপুরি অনুমোদিত। এটি অন্যথায় বলে না।

একটি বাস্তবায়নে শিথিল পয়েন্টার সুরক্ষা থাকতে পারে, সেই ক্ষেত্রে কোনও পয়েন্টার মানের বৈধতা এটি নিরাপদে প্রাপ্ত পয়েন্টার মান কিনা তা নির্ভর করে না।

ওহ, সুতরাং এটি কিছু মনে করতে পারে না, আমি কি ভেবেছিলাম। তবে অপেক্ষা করুন ... "না"? তার মানে, এটিও হতে পারে । আমি কিভাবে জানবো?

বিকল্পভাবে, একটি বাস্তবায়নের কঠোর পয়েন্টার সুরক্ষা থাকতে পারে, সেই ক্ষেত্রে রেফারেন্সযুক্ত সম্পূর্ণ অবজেক্টটি গতিশীল স্টোরেজ সময়কালের না হয় এবং পূর্বে পৌঁছনীয় হিসাবে ঘোষণা না করা হলে নিরাপদে প্রাপ্ত পয়েন্টার মান নয় এমন পয়েন্টার মানটি একটি অবৈধ পয়েন্টার মান is

অপেক্ষা করুন, তাহলে কি এমনও সম্ভব যে আমাকে declare_reachable()প্রতিটি পয়েন্টারে কল করতে হবে ? আমি কিভাবে জানবো?

এখন, আপনি রূপান্তর করতে পারেন intptr_tযা নিরাপদে নির্ধারিত পয়েন্টারটির পূর্ণসংখ্যা উপস্থাপনা করে , যা সংজ্ঞায়িত is যার জন্য, অবশ্যই, পূর্ণসংখ্যা হিসাবে, এটি পুরোপুরি বৈধ এবং যথাসম্ভব যথাযথভাবে এটি বাড়ানোর জন্য যেমন আপনি চান to
এবং হ্যাঁ, আপনি intptr_tপিছনে কোনও পয়েন্টারে রূপান্তর করতে পারেন , এটিও ভাল-সংজ্ঞায়িত। কেবলমাত্র, আসল মান হিসাবে নয়, এটির আর গ্যারান্টি নেই যে আপনার কাছে নিরাপদে উত্পন্ন পয়েন্টার রয়েছে (স্পষ্টতই)। তবুও, সর্বোপরি, স্ট্যান্ডার্ডের চিঠিতে, বাস্তবায়ন-সংজ্ঞায়িত হওয়ার সময়, এটি করা একটি 100% বৈধ কাজ:

[expr.reinterpret.cast] 5
ইন্টিগ্রাল টাইপ বা গণনা টাইপের একটি মান স্পষ্টভাবে একটি পয়েন্টারে রূপান্তরিত হতে পারে। একটি পয়েন্টার পর্যাপ্ত আকারের পূর্ণসংখ্যায় রূপান্তরিত [...] এবং একই পয়েন্টার প্রকারে ফিরে যায় [...] মূল মান; পয়েন্টার এবং পূর্ণসংখ্যার মধ্যে ম্যাপিংগুলি অন্যথায় বাস্তবায়ন-সংজ্ঞায়িত।

ধরা

পয়েন্টারগুলি কেবলমাত্র সাধারণ পূর্ণসংখ্যা, কেবলমাত্র সেগুলি পয়েন্টার হিসাবে ব্যবহার করার জন্য ঘটে। ওহ যদি সত্যিই হত!
দুর্ভাগ্যক্রমে, এমন আর্কিটেকচার রয়েছে যেখানে এটি একেবারেই সত্য নয় এবং কেবল একটি অবৈধ পয়েন্টার তৈরি করা (এটি ডিপ্রিফারেন্স না করা, এটি কেবলমাত্র পয়েন্টার রেজিস্টারে রাখা) একটি ফাঁদ সৃষ্টি করবে।

সুতরাং এটি "বাস্তবায়ন সংজ্ঞায়িত" এর ভিত্তি। যে, এবং সত্য একটি পয়েন্টার বৃদ্ধিশীল যে যখনই আপনি চান, আপনি দয়া করে পারা অবশ্যই কারণ ওভারফ্লো, যা মান সাথে মোকাবিলা করতে চায় না করে। অ্যাপ্লিকেশন ঠিকানার স্থানের সমাপ্তি ওভারফ্লোয়ের অবস্থানের সাথে একত্রিত নাও হতে পারে এবং নির্দিষ্ট আর্কিটেকচারের পয়েন্টারগুলির জন্য ওভারফ্লো জাতীয় কোনও জিনিস আছে কিনা তা আপনি জানেন না। সব মিলিয়ে এটি একটি দুঃস্বপ্নের জগাখিচুড়ি সম্ভাব্য সুবিধার কোনও সম্পর্কের ক্ষেত্রে নয়।

অন্যদিকে এক অতীতের-অবজেক্ট শর্তের সাথে ডিল করা সহজ: বাস্তবায়ন অবশ্যই নিশ্চিত করতে হবে যে কোনও বস্তু কখনও বরাদ্দ করা হয়নি যাতে ঠিকানার জায়গার শেষ বাইটটি দখল করা হয়। সুতরাং এটি গ্যারান্টি হিসাবে দরকারী এবং তুচ্ছ হিসাবে এটি সংজ্ঞায়িত।


1
আপনার যুক্তি ত্রুটিযুক্ত। "তাহলে আপনার কোনও জিনিসই আদৌ দরকার নেই?" একক নিয়মে ফোকাস করে স্ট্যান্ডার্ডকে ভুল ব্যাখ্যা করে। আপনার প্রোগ্রামটি সুগঠিত কিনা তা সেই নিয়মটি সংকলনের সময় সম্পর্কে। রান টাইম সম্পর্কে আরও একটি নিয়ম রয়েছে। কেবলমাত্র রান সময় আপনি কোনও নির্দিষ্ট ঠিকানায় আসলে বস্তুর অস্তিত্ব সম্পর্কে কথা বলতে পারেন। আপনার প্রোগ্রামটি সমস্ত নিয়ম পূরণ করা প্রয়োজন ; সংকলন সময়ে সংকলন-সময় নিয়ম এবং রান সময়ে রান-টাইম বিধি।
এমসাল্টারস

5
"ঠিক আছে, কে যত্ন করে! আপনার স্মৃতিতে কোথাও পয়েন্টার পয়েন্ট করা পর্যন্ত আমি ভাল আছি?"। না। আপনাকে সমস্ত নিয়ম মেনে চলতে হবে। কঠিন ভাষা সম্পর্কে "এক অ্যারে হচ্ছে শেষ আরেকটি অ্যারের শুরু" শুধু দেয় বাস্তবায়ন contiguously মেমরি বরাদ্দ করার অনুমতি; এটি বরাদ্দ মধ্যে ফাঁকা স্থান রাখা প্রয়োজন হয় না। এর অর্থ এই যে আপনার কোডের একটি অ্যারে অবজেক্টের শেষে এবং অন্যটির সূচনা উভয়ের সমান মান একই হতে পারে।
এমসাল্টারস

1
"একটি ফাঁদ" এমন কিছু নয় যা "বাস্তবায়ন সংজ্ঞায়িত" আচরণের মাধ্যমে বর্ণনা করা যায়। নোট করুন যে ইন্টারজয় +অপারেটরের (যে থেকে ++প্রবাহিত হবে) বাধা আবিষ্কার করেছেন যার অর্থ "একের পরের শেষে" নির্দেশ করা অপরিজ্ঞাত ।
মার্টিন বোনার

1
@ পিটারকর্ডস: অনুগ্রহ করে বেসিক.এসটিসি, অনুচ্ছেদ 4 পড়ুন । এটি বলে "" নির্দেশনা [...] অপরিবর্তিত আচরণ an অবৈধ পয়েন্টার মানের অন্য কোনও ব্যবহারের ক্ষেত্রে প্রয়োগ-সংজ্ঞায়িত আচরণ থাকে " । আমি এই শব্দটিকে অন্য অর্থের জন্য ব্যবহার করে বিভ্রান্ত করছি না। এটি হুবহু শব্দ। এটা তোলে হয় না আচরণ undefined।
দামন

2
সবেমাত্র সম্ভব আপনি পোস্ট-ইনক্রিমেন্টের জন্য একটি ফাঁক খুঁজে পেয়েছেন তবে পোস্ট-ইনক্রিমেন্ট কী করে তার পুরো বিভাগটি উদ্ধৃত করেন না। আমি এখনই নিজের দিকে নজর রাখছি না। সম্মত হয়েছে যে যদি একটি থাকে তবে তা অনিচ্ছাকৃত। যাইহোক, আইএসও সি ++ ফ্ল্যাট মেমোরি মডেলগুলির জন্য আরও কিছু সংজ্ঞায়িত করার মত সুন্দর হবে, @ ম্যাক্সিম এগারোশকিন, স্বেচ্ছাসেবী স্টাফগুলিকে অনুমতি না দেওয়ার জন্য অন্যান্য কারণ (পয়েন্টার মোড়কের চারপাশের) রয়েছে। মন্তব্যসমূহ দেখুন পয়েন্টার তুলনা কি স্বাক্ষরিত বা 64-বিট x86 এ স্বাক্ষরিত হওয়া উচিত?
পিটার কর্ডেস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.