সি ++ কম্পাইলাররা কীভাবে কোনও বহিরাগত পরিবর্তনশীল সন্ধান করতে পারেন?


15

আমি এই প্রোগ্রামটি g ++ এবং ঝনঝন ++ দ্বারা সংকলন করি। একটি পার্থক্য রয়েছে:
জি ++ প্রিন্ট ১, তবে ঝাঁকুনি ++ প্রিন্ট ২.
মনে হয়
জি ++: বহিরাগত ভেরিয়েবলটি স্বল্পতম স্কোপে সংজ্ঞায়িত করা হয়েছে।
ঝনঝন ++: বাহ্যিক চলকটি সংক্ষিপ্ততর বিশ্ব ব্যাপ্তিতে সংজ্ঞায়িত করা হয়।

সি ++ স্পকে কি সে সম্পর্কে কোনও স্পেসিফিকেশন রয়েছে?

main.cpp

#include <iostream>
static int i;
static int *p = &i;

int main() {
  int i;
  {
    extern int i;
    i = 1;
    *p = 2;
    std::cout << i << std::endl;
  }
}

other.cpp

int i;

সংস্করণ: জি ++: 7.4.0 / বাধা ++: 10.0.0
সংকলন: $ (সিএক্সএক্স) মেইন সিপ্পি অন্য সিপিপি-বহিরাগত.এক্সে


4
সংকলক বাহ্যিক রেফারেন্সযুক্ত ভেরিয়েবল হিসাবে চিহ্নিত করা ছাড়া বহিরাগতের সাথে কিছুই করে না, লিঙ্কার হ'ল যা সমস্ত সংকলিত বস্তুর ফাইলগুলির মধ্যে লিঙ্কগুলি সমাধান করার চেষ্টা করে।
lat ই

একটি দুর্দান্ত (যদি আশ্চর্যজনক) প্রশ্ন! আপনার কোডটি MSVCএবং clang-cl(উভয়ই দেওয়া 2) দিয়ে খেলে , মনে হয় এটি extern int iউভয় দ্বারা সম্পূর্ণ উপেক্ষা করা হয়েছে: আমি যদি other.cppফাইলে লিঙ্ক না করি তবে প্রোগ্রামটি তৈরি করে এবং চালিত হয়।
অ্যাড্রিয়ান মোল

1
@ স্প্ল্যাটেন সম্ভবতঃ লিঙ্কারের রেফারেন্সটির 'সমাধান' করার দরকার iনেই, এটি চেষ্টা করে না।
অ্যাড্রিয়ান মোল

3
সংশ্লিষ্ট পুরাতন স্থগিত জিসিসি বাগ খুঁজে পাওয়া যেতে পারে এখানে এবং সংশ্লিষ্ট খোলা ঝনঝন বাগ এখানে
আখরোট

উত্তর:


11

[বেসিক.লিংক /]] মানের প্রাসঙ্গিক অংশ হওয়া উচিত। বর্তমান খসড়ায় এটি বলে:

ব্লক স্কোপে ঘোষিত কোনও ফাংশনের নাম এবং একটি ব্লক স্কোপ externঘোষণার মাধ্যমে ঘোষিত একটি চলকের নামের যোগসূত্র রয়েছে। যদি এই জাতীয় ঘোষণাটি কোনও নামযুক্ত মডিউলের সাথে সংযুক্ত থাকে, তবে প্রোগ্রামটি দুর্গঠিত। যদি যোগসূত্রের সাথে কোনও সত্তার দৃশ্যমান ঘোষণা থাকে, তবে অন্তর্নিহিত losের নামকরণ ক্ষেত্রের বাইরে ঘোষিত সত্তাগুলি উপেক্ষা করে যেমন ব্লক স্কোপ ঘোষণাটি একটি (সম্ভবত অসৎ-গঠিত) পুনরায় ঘোষণা হবে যদি দুটি ঘোষণা একই ঘোষণামূলক অঞ্চলে হাজির হয়, ব্লক স্কোপ ডিক্লেয়ারেশন সেই একই সত্তা ঘোষণা করে এবং পূর্বের ঘোষণার লিংকেজ গ্রহণ করে। যদি এইরকম একের বেশি সংখ্যক সত্ত্বা থাকে তবে প্রোগ্রামটি খারাপভাবে তৈরি। অন্যথায়, যদি কোনও মিলে যাওয়া সত্তাটি পাওয়া যায় না, তবে ব্লক স্কোপ সত্তা বাহ্যিক লিঙ্কেজ গ্রহণ করে।যদি, কোনও অনুবাদ ইউনিটের মধ্যে, একই সত্ত্বা অভ্যন্তরীণ এবং বাহ্যিক উভয় সংযোগের সাথে ঘোষণা করা হয়, তবে প্রোগ্রামটি দুর্বল।

নোট করুন যে পরবর্তী উদাহরণটি আপনার ক্ষেত্রে প্রায় হুবহু মিলে যায়:

static void f();
extern "C" void h();
static int i = 0;               // #1
void g() {
  extern void f();              // internal linkage
  extern void h();              // C language linkage
  int i;                        // #2: i has no linkage
  {
    extern void f();            // internal linkage
    extern int i;               // #3: external linkage, ill-formed
  }
}

সুতরাং, প্রোগ্রামটি খারাপভাবে গঠন করা উচিত। ব্যাখ্যা নীচে নীচে:

লাইন # 2 এ ঘোষণা ছাড়াই, লাইন # 3 এ ঘোষণাটি লাইন # 1-এ ঘোষণার সাথে যুক্ত হবে। কারণ অভ্যন্তরীণ সংযোগ সহ ঘোষণাটি গোপন করা আছে, তবে, # 3টিকে বাহ্যিক সংযোগ দেওয়া হয়েছে, যা প্রোগ্রামটিকে দুর্গঠিত করে।


উদাহরণস্বরূপ প্রোগ্রামটি দুর্গঠিত, কারণ বাহ্যিক সংযোগের সাথে কোথাও সংজ্ঞায়িত কোনও আই নেই । ওপির উদাহরণের ক্ষেত্রে এটি হয় না।
এন। 'সর্বনাম' মি।

3
@ n.'pronouns'm। তবে নিয়মটি অনুবাদ ইউনিটে প্রযোজ্য: যদি কোনও অনুবাদ ইউনিটের মধ্যে, একই সত্তা অভ্যন্তরীণ এবং বাহ্যিক উভয় সংযোগের সাথে ঘোষিত হয় তবে প্রোগ্রামটি দুর্গঠিত।
ড্যানিয়েল ল্যাঙ্গার

2
উত্তরটি কেবলমাত্র C ++ 17 এবং তার পরে প্রযোজ্য, সিডাব্লুজি ইস্যুতে 426 এর সমাধান দেখুন । আমার কাছে মনে হয় যে পরিবর্তনের আগে জিসিসি সঠিক ছিল।
আখরোট

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