কেন (কেবল) কিছু সংকলক একই পংক্তির অক্ষরের জন্য একই ঠিকানা ব্যবহার করবেন?


92

https://godbolt.org/z/cyBiWY

আমি 'some'এমএসভিসি দ্বারা উত্পাদিত এসেম্বলার কোডে দুটি আক্ষরিক দেখতে পাই , তবে কেবল ঝাঁকুনি এবং জিসিসি সহ। এটি কোড কার্যকর করার সম্পূর্ণ ভিন্ন ফলাফলের দিকে নিয়ে যায়।

static const char *A = "some";
static const char *B = "some";

void f() {
    if (A == B) {
        throw "Hello, string merging!";
    }
}

এই সংকলনের ফলাফলগুলির মধ্যে কেউ পার্থক্য এবং সাদৃশ্য ব্যাখ্যা করতে পারে? কোনও অপ্টিমাইজেশন অনুরোধ না করা সত্ত্বেও কেন ঝনঝন / জিসিসি কিছু অনুকূল করে? এটি কি একরকম অবধারিত আচরণ?

আমি আরও লক্ষ্য করেছি যে আমি যদি নীচে দেখানো অনুসারে ঘোষণাগুলি পরিবর্তন করি তবে ঝাঁকুনি / জিসিসি / এমএসভিসি এসেম্বলারের কোডে মোটেও ছাড়বে না "some"। আচরণ আলাদা কেন?

static const char A[] = "some";
static const char B[] = "some";

4
stackoverflow.com/a/52424271/1133179 স্ট্যান্ডার্ড কোট সহ একটি নিবিড়ভাবে সম্পর্কিত প্রশ্নের কয়েকটি দুর্দান্ত প্রাসঙ্গিক উত্তর
luk32


6
এমএসভিসির জন্য, / জিএফ সংকলক বিকল্পটি এই আচরণটি নিয়ন্ত্রণ করে। দেখুন docs.microsoft.com/en-us/cpp/build/reference/...
Sjoerd

4
এফওয়াইআই, এটি কার্যক্রমেও ঘটতে পারে।
ব্যবহারকারী541686

উত্তর:


109

এটি অনির্ধারিত আচরণ নয়, তবে অনির্দিষ্ট আচরণ। জন্য স্ট্রিং লিটারেল ,

সংকলকটি সমান বা ওভারল্যাপিং স্ট্রিং লিটারেলের জন্য স্টোরেজ একত্রিত করার অনুমতি দেওয়া হয়েছে তবে প্রয়োজনীয় নয়। এর অর্থ হ'ল অভিন্ন স্ট্রিং লিটারালগুলি পয়েন্টারের সাথে তুলনা করার সময় সমান তুলনা করতে পারে বা নাও করতে পারে।

এর অর্থ হ'ল ফলাফল বা A == Bহতে পারে , যার উপর আপনার নির্ভর করা উচিত নয়।truefalse

স্ট্যান্ডার্ড থেকে, [lex.string] / 16 :

সমস্ত স্ট্রিং আক্ষরিক স্বতন্ত্র কিনা (তা হ'ল ননওভারল্যাপিং অবজেক্টগুলিতে সংরক্ষিত থাকে) এবং স্ট্রিং-আক্ষরিক ফলনটির ক্রমাগত মূল্যায়ন একই বা অন্য কোনও অবজেক্টের অনির্দিষ্ট কিনা।


36

অন্যান্য উত্তরগুলি ব্যাখ্যা করেছে যে আপনি কেন পয়েন্টার ঠিকানাগুলি আলাদা হওয়ার আশা করতে পারবেন না। তবুও আপনি সহজেই এটিকে এমনভাবে পুনরায় লিখতে পারেন যা গ্যারান্টি দেয় Aএবং Bসমান তুলনা করে না:

static const char A[] = "same";
static const char B[] = "same";// but different

void f() {
    if (A == B) {
        throw "Hello, string merging!";
    }
}

পার্থক্যটি হ'ল Aএবং Bএখন অক্ষরের অ্যারে। এর অর্থ হ'ল এগুলি পয়েন্টার নয় এবং তাদের ঠিকানা দুটি পৃথক পূর্ণরূপের মতো হওয়া উচিত have সি ++ এটিকে বিভ্রান্ত করে কারণ এটি পয়েন্টার এবং অ্যারেগুলিকে বিনিময়যোগ্য বলে মনে হয় ( operator*এবং operator[]একইরকম আচরণ করে বলে মনে হয়) তবে তারা সত্যই আলাদা। যেমন এর মতো const char *A = "foo"; A++;কিছু পুরোপুরি আইনী, তবে const char A[] = "bar"; A++;তা নয়।

পার্থক্যটি সম্পর্কে ভাবার একটি উপায় হ'ল char A[] = "...""আমাকে একটি স্মৃতিশক্তি দিন এবং ...তারপরে অক্ষরগুলি পূরণ করুন \0", যেখানে char *A= "...""আমাকে একটি ঠিকানা দিন যেখানে আমি ...অনুসরণ করা অক্ষরগুলি খুঁজে পেতে পারি \0"।


8
এটি কেন আরও আলাদা তা যদি আপনি ব্যাখ্যা করতে পারেন তবে এটি আরও উত্তম উত্তর হবে।
মার্ক রান্সম

লক্ষ্য করুন *pএবং p[0]শুধুমাত্র না কিন্তু সংজ্ঞা দ্বারা "একই আচরণ বলে মনে হচ্ছে" হয় অভিন্ন (প্রদান করা p+0 == pএকটি পরিচয় সম্পর্ক নেই কারণ 0পয়েন্টার-পূর্ণসংখ্যা ছাড়াও নিরপেক্ষ উপাদান)। সর্বোপরি, p[i]হিসাবে সংজ্ঞায়িত করা হয় *(p+i)। উত্তর যদিও একটি ভাল পয়েন্ট তোলে।
পিটার - মনিকাকে

typeof(*p)এবং typeof(p[0])উভয় charতাই সত্যিই খুব বেশি বাকি আছে যে আলাদা হতে পারে। আমি সম্মত হই যে '' একইরকম আচরণ করে বলে মনে হচ্ছে '' সর্বোত্তম শব্দ নয়, কারণ শব্দার্থবিজ্ঞানগুলি এত আলাদা different আপনার পোস্ট সি ++ অ্যারে অ্যাক্সেস উপাদানের করার সেরা উপায় আমার মনে করিয়ে দিয়েছিলেন: 0[p], 1[p], 2[p]ইত্যাদি এভাবেই অনুকূল এটা করতে, অন্তত যখন তারা যারা C প্রোগ্রামিং ভাষা পর জন্ম হয় গুলান করতে চান।
tobi_s


এটি আকর্ষণীয়, এবং আমি সি এফএকিউতে একটি লিঙ্ক যুক্ত করার জন্য প্রলুব্ধ হয়েছিলাম, তবে আমি বুঝতে পেরেছিলাম যে এখানে প্রচুর সম্পর্কিত প্রশ্ন রয়েছে, তবে এখানে এই প্রশ্নের বিন্দুটি সঠিকভাবে কাটেনি বলে মনে হচ্ছে।
tobi_s

23

কোনও সংকলক একই স্ট্রিং অবস্থানটি ব্যবহার করতে পছন্দ করে Aএবং Bতা বাস্তবায়নের উপর নির্ভর করে কিনা। সাধারণত আপনি বলতে পারেন যে আপনার কোডের আচরণটি অনির্ধারিত

উভয় পছন্দই সি ++ স্ট্যান্ডার্ডকে সঠিকভাবে প্রয়োগ করে।


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

3

এটি স্থান সংরক্ষণের একটি অপ্টিমাইজেশন, প্রায়শই "স্ট্রিং পুলিং" নামে পরিচিত। এমএসভিসির জন্য দস্তাবেজগুলি এখানে:

https://msdn.microsoft.com/en-us/library/s0s0asdt.aspx

অতএব আপনি যদি কমান্ড লাইনে / জিএফ যুক্ত করেন তবে আপনার এমএসভিসির সাথে একই আচরণ দেখতে হবে।

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

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.