গ্লোবাল ভেরিয়েবল সহ একটি প্রোগ্রাম কীভাবে মূল ফাংশনটির পরিবর্তে প্রধান নামে পরিচিত?


97

নিম্নলিখিত প্রোগ্রাম বিবেচনা করুন:

#include <iostream>
int main = ( std::cout << "C++ is excellent!\n", 195 ); 

উইন্ডোজ 7 ওএসে জি ++ 4.8.1 (মিংডব্লু 64) ব্যবহার করে প্রোগ্রামটি সংকলন করে সূক্ষ্মভাবে চালিত হয়, মুদ্রণ:

সি ++ দুর্দান্ত!

কনসোল থেকে। mainএকটি ফাংশন পরিবর্তে বৈশ্বিক পরিবর্তনশীল হিসাবে উপস্থিত হয়; এই প্রোগ্রামটি কীভাবে ফাংশন ছাড়াই কার্যকর করতে পারে main()? এই কোডটি কি সি ++ স্ট্যান্ডার্ডের সাথে খাপ খায়? প্রোগ্রামটির আচরণটি কি সংজ্ঞাযুক্ত? আমি -pedantic-errorsবিকল্পটিও ব্যবহার করেছি তবে প্রোগ্রামটি এখনও সংকলন করে চলে।


11
@ πάνταῥεῖ: ভাষার উকিল ট্যাগ কেন প্রয়োজনীয়?
ধ্বংসকারী

14
নোটটি সেই নির্দেশের 195জন্য অপকড RETএবং সি কলিং কনভেনশনে কলার স্ট্যাকটি সাফ করে দেয়।
ব্রায়ান

4
@ প্রবাসীমিট "তাহলে এই প্রোগ্রামটি কীভাবে কার্যকর করে" - আপনি কী ভেরিয়েবলের প্রারম্ভিককরণ কোডটি কার্যকর করা উচিত বলে মনে করেন না (এমনকি main()ফাংশন ব্যতীত? তারা সম্পূর্ণ অপ্রাসঙ্গিক।)
প্যারাম্যাগনেটিক ক্রোস্যান্ট

4
আমি তাদের মধ্যে যারা পেয়েছি যে প্রোগ্রামটি সেগফাল্টস হিসাবে রয়েছে (64৪-বিট লিনাক্স, জি ++ 5.1 / ঝনঝন 3.6)। আমি তবে এটিকে সংশোধন করে এটি সংশোধন করতে পারি int main = ( std::cout << "C++ is excellent!\n", exit(0),1 );(এবং সহ <cstdlib>) প্রোগ্রামটি আইনানুগভাবে দূর্গঠিত থাকা সত্ত্বেও।
মাইক কিংহান

11
@ ব্রায়ান যেমন বিবৃতি দেওয়ার সময় আপনার স্থাপত্যের উল্লেখ করা উচিত mention সমস্ত পৃথিবী ভ্যাক্স নয়। বা x86। বা যাই হোক না কেন.
ডিএমকেকে --- প্রাক্তন মডারেটর বিড়ালছানা

উত্তর:


85

কি চলছে এই প্রশ্নের মাংসে goingোকার আগে, এটি উল্লেখ করা গুরুত্বপূর্ণ যে ত্রুটি প্রতিবেদন 1886 অনুসারে প্রোগ্রামটি খারাপভাবে তৈরি হয়েছে : মূল () এর জন্য ভাষা সংযোগ :

[...] এমন একটি প্রোগ্রাম যা বৈশ্বিক স্কোপে একটি পরিবর্তনশীল প্রধান ঘোষণা করে বা সি ভাষার লিঙ্কেজ (যে কোনও নামস্থানে) সহ নাম মেইন ঘোষনা করে তা খারাপ-গঠিত। [...]

ক্ল্যাং এবং জিসিসির সাম্প্রতিকতম সংস্করণগুলি এটিকে ত্রুটি করে তোলে এবং প্রোগ্রামটি সংকলন করবে না ( জিসিসির সরাসরি উদাহরণ দেখুন ):

error: cannot declare '::main' to be a global variable
int main = ( std::cout << "C++ is excellent!\n", 195 ); 
    ^

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

এর আগে, মনে মত এই অনির্ধারিত আচরণ কেমন হওয়া উচিৎ, যেহেতু আমরা একটি লঙ্ঘন করে তা দেখুন হইবে খসড়া C- এর প্রয়োজন ++, অধ্যায় থেকে মান 3.6.1 [basic.start.main] :

একটি প্রোগ্রামে মূল নামে একটি বিশ্বব্যাপী ফাংশন থাকবে যা প্রোগ্রামটির মনোনীত শুরু। [...]

অপরিজ্ঞাত আচরণটি অনির্দেশ্য এবং এ জন্য ডায়াগনস্টিকের প্রয়োজন হয় না। আচরণটি পুনরুত্পাদন করার সাথে আমরা যে অসঙ্গতি দেখি তা হ'ল সাধারণ অপরিজ্ঞাত আচরণ।

সুতরাং কোডটি আসলে কী করছে এবং কেন কিছু ক্ষেত্রে এটি ফলাফল দেয়? আসুন দেখুন আমাদের কী আছে:

declarator  
|        initializer----------------------------------
|        |                                           |
v        v                                           v
int main = ( std::cout << "C++ is excellent!\n", 195 ); 
    ^      ^                                   ^
    |      |                                   |
    |      |                                   comma operator
    |      primary expression
global variable of type int

আমরা আশা করি আপনি mainযা হয় int- এ বিশ্বব্যাপী নামস্থান ঘোষণা এবং সক্রিয়া করা হচ্ছে, পরিবর্তনশীল স্ট্যাটিক স্টোরেজ সময়কাল হয়েছে। এটি প্রয়োগের সংজ্ঞায়িত হয় যে কল করার চেষ্টা করার আগে আরম্ভ হবে কিনা mainতবে এটি প্রদর্শিত হয় জিসিসি কল করার আগে এটি করে না main

কোডটি কমা অপারেটর ব্যবহার করে , বাম অপারেন্ডটি একটি বাতিল হওয়া মূল্য প্রকাশ এবং এটি কেবলমাত্র কলিংয়ের পার্শ্ব প্রতিক্রিয়ার জন্য ব্যবহৃত হয় std::cout। কমা অপারেটরের ফলাফলটি হ'ল অপারেন্ড যা এই ক্ষেত্রে 195ভেরিয়েবলের জন্য নির্ধারিত অগ্রগতি main

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

main:
.zero   4

এবং পরবর্তী:

movl    $195, main(%rip)

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

দেখা যাচ্ছে আমরা সি সি ব্যবহার করে এটি জিসিসি পেতে পারি ( এটি সরাসরি দেখুন ):

const int main = 195 ;

এটি সিগ-ত্রুটিগুলি যদি ভেরিয়েবলটি mainসম্ভবত নির্ধারিত না হয় কারণ এটি একটি নির্বাহযোগ্য স্থানে অবস্থিত না হয় তবে এই মন্তব্যটির জন্য এখানে হ্যাট টিপ যা আমাকে এই ধারণা দিয়েছে।

এছাড়াও এই প্রশ্নের সি নির্দিষ্ট সংস্করণে এখানে FUZxxl উত্তরটি দেখুন ।


বাস্তবায়ন কেন কোনও সতর্কতা দিচ্ছে না। (যখন আমি-ওয়াল এবং-ওয়েক্সট্রা ব্যবহার করি এটি এখনও একক সতর্কতা দেয় না)। কেন? @ মার্ক বি এর এই প্রশ্নের উত্তর সম্পর্কে আপনি কী মনে করেন?
ডেস্ট্রাক্টর

আইএমএইচও, mainসংকলকটি কোনও সতর্কতা দেবে না কারণ কোনও সংরক্ষিত শনাক্তকারী নয় (3.6.1 / 3)। এই ক্ষেত্রে, আমি মনে করি ভিসি ২০১৩ এর এই কেসটি পরিচালনা করা (ফ্রান্সিস কিগ্রারের উত্তর দেখুন) এটি জিসিসি এবং ঝনঝনির চেয়ে বেশি পরিচালনা করছে।
সিডিএমএইচ

@ প্রবাসীমিট আমি জিসিসির পূর্ববর্তী সংস্করণগুলি কেন ডায়াগনস্টিক দেয়নি সে সম্পর্কে আমি আমার উত্তরটি আপডেট করেছি।
শফিক ইয়াঘমোর

4
... এবং প্রকৃতপক্ষে, যখন আমি লিনাক্স / x86-64 এ ওপি-র প্রোগ্রামটি জি ++ 5.2 দিয়ে পরীক্ষা করি (যা প্রোগ্রামটি গ্রহণ করে - আমি অনুমান করি যে আপনি "অতি সাম্প্রতিক সংস্করণ" সম্পর্কে মজা করছেন না) এটি ক্র্যাশ হয়ে গেছে যেখানে আমি এটি প্রত্যাশা করেছি হবে।
zwol

4
@ ওয়াল্টার আমি বিশ্বাস করি না যে এগুলি সেই নকল যা প্রাক্তন অনেক সংকীর্ণ প্রশ্ন জিজ্ঞাসা করছেন। স্পষ্টত এসও ব্যবহারকারীর একটি গ্রুপ রয়েছে যা নকলগুলি সম্পর্কে আরও হ্রাসমূলক দৃষ্টিভঙ্গি রাখে যা আমি আমার পক্ষে খুব একটা বোধ করি না যেহেতু আমরা বেশিরভাগ এসও প্রশ্নগুলিকে পুরানো প্রশ্নগুলির কয়েকটি সংস্করণে সিদ্ধ করতে পারি তবে এসও খুব কার্যকর হবে না।
শফিক ইয়াঘমোর

20

৩.6.১ / ১ থেকে:

একটি প্রোগ্রামে মূল নামে একটি বিশ্বব্যাপী ফাংশন থাকবে যা প্রোগ্রামটির মনোনীত শুরু। এটি বাস্তবায়ন সংজ্ঞায়িত হয় যে একটি ফ্রিস্ট্যান্ডিং পরিবেশে কোনও প্রোগ্রাম একটি মূল ফাংশন সংজ্ঞায়িত করতে প্রয়োজন কিনা।

এ থেকে দেখে মনে হচ্ছে যে জি ++ কোনও মূল ফাংশন ছাড়াই কোনও প্রোগ্রাম (সম্ভবত "ফ্রিস্ট্যান্ডিং" ধারা হিসাবে) অনুমতি দেয় happens

তারপরে 3.6.1 / 3 থেকে:

ফাংশন প্রধান কোনও প্রোগ্রামের মধ্যে ব্যবহার করা হবে না (3.2)। মূল লিঙ্কেজ (3.5) বাস্তবায়ন সংজ্ঞায়িত করা হয়। একটি প্রোগ্রাম যা মূলটিকে ইনলাইন বা স্থিতিশীল হিসাবে ঘোষিত হয় তা অজ্ঞাত। নামটির নামটি অন্যথায় সংরক্ষিত নয়।

সুতরাং এখানে আমরা শিখলাম যে একটি পূর্ণসংখ্যার ভেরিয়েবল নামকরণ করা পুরোপুরি ঠিক main

অবশেষে যদি আপনি ভাবছেন যে কেন আউটপুট মুদ্রিত হয়, int mainব্যবহারের সূচনাটি কমা অপারেটরটিকে coutস্ট্যাটিক init এ কার্যকর করতে ব্যবহার করে এবং তারপর আরম্ভ করার জন্য একটি প্রকৃত অবিচ্ছেদ্য মান সরবরাহ করে।


7
আকর্ষণীয় বিষয় এটি লক্ষণীয় যে আপনি যদি mainঅন্য কোনও নামকরণ করেন তবে লিঙ্কিং ব্যর্থ হয় : (.text+0x20): undefined reference to মূল '`
ফ্রেড লারসন

4
আপনার প্রোগ্রামটি ফ্রিস্ট্যান্ডিং হচ্ছে তা আপনাকে জিসিসি নির্দিষ্ট করতে হবে না?
শফিক ইয়াঘমোর

9

gcc 4.8.1 নিম্নলিখিত x86 সমাবেশ উত্পন্ন করে:

.LC0:
    .string "C++ is excellent!\n"
    subq    $8, %rsp    #,
    movl    std::__ioinit, %edi #,
    call    std::ios_base::Init::Init() #
    movl    $__dso_handle, %edx #,
    movl    std::__ioinit, %esi #,
    movl    std::ios_base::Init::~Init(), %edi  #,
    call    __cxa_atexit    #
    movl    $.LC0, %esi #,
    movl    std::cout, %edi #,
    call    std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)   #
    movl    $195, main(%rip)    #, main
    addq    $8, %rsp    #,
    ret
main:
    .zero   4

নোট যে ফাংশন coutনয়, আরম্ভের সময় বলা হয় main!

.zero 4অবস্থান থেকে শুরু করে 4 (0-আরম্ভ) বাইট ঘোষণা করে main, যেখানে ভেরিয়েবলেরmain নাম [!]

mainপ্রতীক কর্মসূচি শুরুর হিসেবে ব্যাখ্যা করা হয়। আচরণ প্ল্যাটফর্মের উপর নির্ভর করে।


4
নোট করুন যেমন ব্রায়ান কিছু আর্কিটেকচারের 195জন্য অপকড ret। সুতরাং শূন্য নির্দেশাবলী বলা সঠিক নাও হতে পারে।
শফিক ইয়াঘমোর

@ শাফিক ইয়্যাগমোর আপনার মন্তব্যের জন্য ধন্যবাদ, আপনি ঠিক বলেছেন। আমি একত্রিতকারীর নির্দেশাবলীতে গণ্ডগোল পেয়েছি।
সার্জেজ

8

এটি একটি দুর্গঠিত প্রোগ্রাম। এটি আমার পরীক্ষার পরিবেশে সাইগউইন /৪ / জি ++ ৪.৯.৩ ক্র্যাশ করে।

মান থেকে:

৩.6.১ মূল ফাংশন [বেসিক.স্টার্ট.মাইন]

1 একটি প্রোগ্রামে মূল নামে একটি বিশ্বব্যাপী ফাংশন থাকবে যা প্রোগ্রামটির মনোনীত শুরু।


আমি মনে করি যে ত্রুটিযুক্ত প্রতিবেদনের আগে আমি উদ্ধৃত করেছি, এটি ছিল কেবল সাধারণ অপরিবর্তিত আচরণ।
শফিক ইয়াঘমোর

@ শফিকিক ইয়াঝমুর, মানকটি যে সমস্ত জায়গায় ব্যবহার করা উচিত সেখানে যে সাধারণ নীতিটি প্রয়োগ করা হবে তা কি?
আর সাহু

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

4
C99 বিভাগ 4 ("কনফারেন্স") এটিকে দ্ব্যর্থহীন করে তোলে: "যদি কোনও বাধা বাহিরের বাইরে উপস্থিত 'আবশ্যক' বা 'আবশ্যক না' প্রয়োজনীয়তা লঙ্ঘিত হয় তবে আচরণটি অনির্ধারিত। আমি সি ++ 98 বা সি ++ 11-তে সমতুল্য শব্দগুলি খুঁজে পাচ্ছি না, তবে আমি দৃ strongly়ভাবে সন্দেহ করি যে কমিটিটি এটি ছিল meant (সি এবং সি ++ কমিটিগুলিকে সত্যই বসে থাকতে হবে এবং দুটি মানের মধ্যে থাকা সমস্ত পরিভাষাগত পার্থক্য খুঁজে বের করতে হবে ।)
zwol

7

কারণ আমার বিশ্বাস এই কাজ করে যে কম্পাইলার যে এটি কম্পাইল হচ্ছে জানে না main()ফাংশন তাই এটি কাজ পার্শ্ব প্রতিক্রিয়া সঙ্গে একটি বিশ্বব্যাপী পূর্ণসংখ্যা প্রনয়ন।

বস্তু বিন্যাস যে এই অনুবাদ ইউনিট মধ্যে কম্পাইল করা হয় মধ্যে পার্থক্য করতে সক্ষম নয় ফাংশন প্রতীক এবং পরিবর্তনশীল প্রতীক

সুতরাং লিঙ্কার আনন্দের সাথে (পরিবর্তনশীল) প্রধান প্রতীকটিতে লিঙ্ক করে এবং এটি একটি ফাংশন কলের মতো আচরণ করে। তবে রানটাইম সিস্টেম গ্লোবাল ভেরিয়েবল ইনিশিয়ালেশন কোডটি চালনা না করা পর্যন্ত নয় ।

আমি যখন নমুনাটি ছাপিয়েছিলাম তা ছাপিয়েছি তবে তারপরে এটি একটি সেগ-ত্রুটি ঘটায় । আমি ধরে নিয়েছি যে যখন রানটাইম সিস্টেমটি কোনও ইনট ভেরিয়েবল কার্যকর করার চেষ্টা করেছিল যেন এটি কোনও ফাংশন


4

আমি ভিএস ২০১৩ ব্যবহার করে একটি উইন 64৪ বিবিট ওএস এ চেষ্টা করেছি এবং এটি সঠিকভাবে সংকলন করেছে তবে যখন আমি অ্যাপ্লিকেশনটি তৈরির চেষ্টা করব তখন আমি এই বার্তাটি আউটপুট উইন্ডো থেকে পাই।

1>------ Build started: Project: tempTest, Configuration: Debug Win32 ------
1>LINK : fatal error LNK1561: entry point must be defined
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

4
এফডাব্লুআইডাব্লু, এটি একটি লিঙ্কার ত্রুটি, ডিবাগার থেকে কোনও বার্তা নয়। সংকলন সফল, কিন্তু linker একটি ফাংশন খুঁজে পাইনি main()কারণ এটি ধরনের একটি পরিবর্তনশীল এরint
cdmh

উত্তরের জন্য ধন্যবাদ আমি এটির প্রতিফলন করতে আমার প্রাথমিক উত্তরটি লিখব।
ফ্রান্সিস কিউলার

-1

আপনি এখানে কৃপণ কাজ করছেন। প্রধান হিসাবে (একরকম) পূর্ণসংখ্যা হিসাবে ঘোষণা হতে পারে। আপনি বার্তা প্রিন্ট করতে তালিকা অপারেটর ব্যবহার করেছেন এবং তারপরে এটি 195 বন্টন করুন। নীচে কেউ বলেছেন যে, এটি সি ++ দিয়ে সান্ত্বনা দেয় না, এটি সত্য। সংকলক হিসাবে কোনও ব্যবহারকারীর সংজ্ঞায়িত নাম, প্রধান এটি খুঁজে পায় নি, এটি অভিযোগ করেনি। মনে রাখবেন প্রধান হ'ল সিস্টেম সংজ্ঞায়িত ফাংশন নয়, এর ব্যবহারকারীর সংজ্ঞায়িত ফাংশন এবং যা থেকে প্রোগ্রামটি চালানো শুরু হয় তা মূল মডিউল, প্রধান নয় () specifically আবার মেইন () কে স্টার্টআপ ফাংশন বলা হয় যা লোডার ইচ্ছাকৃতভাবে সম্পাদন করে। তারপরে আপনার সমস্ত ভেরিয়েবলগুলি আরম্ভ করা হয়, এবং এটি আরম্ভ করার সময় এর মতো আউটপুট দেয়। এটাই. প্রধান () ব্যতীত প্রোগ্রাম ঠিক আছে, তবে মানক নয়।

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