কী ছাপা হবে? 6 6 বা 6 7? এবং কেন?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
কী ছাপা হবে? 6 6 বা 6 7? এবং কেন?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
উত্তর:
এখানে দুটি বিষয় রয়েছে, জীবনকাল এবং সুযোগ।
ভেরিয়েবলের সুযোগ হ'ল যেখানে পরিবর্তনশীল নামটি দেখা যায়। এখানে এক্স কেবলমাত্র ফাংশন ফু () এর ভিতরে দৃশ্যমান।
পরিবর্তকের জীবনকাল হ'ল সেই সময়কাল যা এটি বিদ্যমান। যদি x কীওয়ার্ড স্ট্যাটিক ব্যতীত সংজ্ঞায়িত করা হয় তবে foo () এ প্রবেশ করা থেকে foo () এ ফিরে আসা; সুতরাং এটি প্রতিটি কল এ পুনরায় আরম্ভ করা হবে 5।
মূলশব্দ স্ট্যাটিক একটি চলকটির আজীবন প্রোগ্রামের আজীবন প্রসারিত করতে কাজ করে; উদাহরণস্বরূপ একবার এবং একবার মাত্র একবার ঘটে এবং তারপরে ভেরিয়েবল তার মান ধরে রাখে - যাই হোক না কেন - ভবিষ্যতে সমস্ত কলকে foo () এ কল করে।
আউটপুট : 6 7
কারণ : স্ট্যাটিক ভেরিয়েবল একবারেই শুরু করা হয় (অটো ভেরিয়েবলের বিপরীতে) এবং স্ট্যাটিক ভেরিয়েবলের আরও সংজ্ঞা রানটাইমের সময় বাইপাস করা হবে। এবং যদি এটি ম্যানুয়ালি আরম্ভ করা হয় না তবে এটি 0 মান দ্বারা স্বয়ংক্রিয়ভাবে শুরু হয়। সুতরাং,
void foo() {
static int x = 5; // assigns value of 5 only once
x++;
printf("%d", x);
}
int main() {
foo(); // x = 6
foo(); // x = 7
return 0;
}
6 7
সংকলকটি স্থির করে দেয় যে প্রতিবার ফাংশনটি প্রবেশ করার পরে স্থির পরিবর্তনশীল সূচনা ঘটে না
নিম্নলিখিত প্রোগ্রাম থাকার মতোই:
static int x = 5;
void foo()
{
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
স্ট্যাটিক কীওয়ার্ডটি সেই প্রোগ্রামটিতে যা কিছু করে তা হ'ল এটি কম্পাইলারকে (মূলত) বলে দেয় 'আরে, আমার এখানে একটি ভেরিয়েবল আছে যে আমি অন্য কারও অ্যাক্সেস চাই না, অন্য কারও কাছে উপস্থিত থাকতে বলব না'।
একটি পদ্ধতির অভ্যন্তরে স্থির কীওয়ার্ড সংকলকটিকে উপরের মতো একই কথা বলে, তবে এটিও 'এই ফাংশনের বাইরে এটি কাউকে বলবেন না যে এটি কেবল এই ফাংশনের অভ্যন্তরে প্রবেশযোগ্য হবে'।
আশা করি এটা কাজে লাগবে
x
; এটি বিশ্বব্যাপী। মূল উদাহরণটি x
ছিল ফু-র কাছে স্থানীয়, কেবলমাত্র সেই ব্লকের অভ্যন্তরে দৃশ্যমান, যা সাধারণত পছন্দনীয়: যদি foo x
অনুমানযোগ্য এবং দৃশ্যমান উপায়ে বজায় রাখার জন্য উপস্থিত থাকে , তবে অন্যকে এড়িয়ে দেওয়া সাধারণভাবে বিপজ্জনক। এটি সুযোগে রাখার আরেকটি সুবিধা হিসাবে এটি পোর্টেবলও foo()
রাখে foo()
।
c
, সুতরাং এই প্রসঙ্গে আপনার বিশ্বব্যাপী সুযোগটি অবৈধ হবে। (সি গ্লোবালগুলির জন্য ধ্রুবক আরম্ভকারী প্রয়োজন, সি ++ দেয় না)।
আপনার প্রোগ্রামটি চলাকালীন কোনও ফাংশনের অভ্যন্তরে স্থির পরিবর্তনশীল একটি জীবনকাল থাকে। আপনার ফাংশনটি যখন ফিরে আসে তখন আপনার ফাংশনটি ডাকা এবং ডিলোকটেডের সময় এটি বরাদ্দ করা হবে না।
ঘোষণাপত্র x
ভিতরে foo
তবে x=5
প্রাথমিকের বাইরেও ঘটে foo
!
আমাদের এখানে যা বোঝার দরকার তা তা
static int x = 5;
হিসাবে একই হয় না
static int x;
x = 5;
অন্যান্য উত্তরগুলি এখানে গুরুত্বপূর্ণ শব্দগুলি, সুযোগ এবং আজীবন ব্যবহার করেছে এবং চিহ্নিত করেছে যে কার্যটি x
তার ঘোষণার বিন্দু থেকে ফাংশনের foo
শেষ অবধি foo
। উদাহরণস্বরূপ, আমি ঘোষণাটি ফাংশনের শেষের দিকে নিয়ে গিয়ে পরীক্ষা করেছিলাম এবং x
এটি x++;
বিবৃতিতে অঘোষিত করে তোলে ।
সুতরাং static int x
বিবৃতিটির (সুযোগ) অংশটি প্রযোজ্য যেখানে আপনি এটি পড়েছেন, কোথাও ফাংশনটি ভিতরে লিখুন এবং কেবল সেখানে থেকে ফাংশনের অভ্যন্তরে নয় not
তবে x = 5
বিবৃতিটির (আজীবন) অংশটি প্রোগ্রাম লোডের অংশ হিসাবে ফাংশনটির পরিবর্তনশীল এবং ঘটমান আউটসাইডের সূচনা হয় । প্রোগ্রামটি লোড x
হওয়ার 5
পরে একটি মান নিয়ে চলক জন্মগ্রহণ করে ।
আমি এগুলির একটি মন্তব্যে এটি পড়েছি: " এছাড়াও, এটি সত্যিকার অর্থে বিভ্রান্তিকর অংশটিকে সম্বোধন করে না, এটিই সত্য যে পরবর্তীকালের কলগুলিতে আরম্ভকারী বাদ দেওয়া হয় " "এটি সমস্ত কলকে বাদ দেওয়া হয়। ভেরিয়েবলের সূচনাটি সঠিকভাবে ফাংশন কোডের বাইরে।
5 এর মানটি তাত্ত্বিকভাবে সেট করা থাকে যা foo এ বলা হয় বা না তা নির্বিশেষে, যদিও কোনও সংকলক যদি আপনি কোথাও কল না করেন তবে এটি ফাংশনটি অপ্টিমাইজ করতে পারে। Foo বলার আগে 5 এর মান পরিবর্তনশীল হওয়া উচিত।
ভিতরে foo
, বিবৃতিতে static int x = 5;
কোনও কোড উত্পন্ন হওয়ার সম্ভাবনা কম।
আমার কোনও প্রোগ্রামে x
কোনও ফাংশন রাখার সময় আমি ঠিকানাটি ব্যবহার করে খুঁজে পেয়েছি foo
এবং তারপরে (সঠিকভাবে) অনুমান করা হয়েছে যে যদি আমি প্রোগ্রামটি আবার চালিত করি তবে একই অবস্থানটি ব্যবহার করা হবে। নীচে আংশিক স্ক্রিন ক্যাপচার দেখায় যে এর প্রথম কল করার আগেই এর x
মান রয়েছে ।5
foo
আউটপুট হবে 6 7
। একটি স্ট্যাটিক ভেরিয়েবল (কোনও ফাংশনের অভ্যন্তরে থাকুক বা না থাকুক) সেই অনুবাদ ইউনিটের কোনও ফাংশন কার্যকর করার আগে ঠিক একবার শুরু করা হয়েছিল utes এর পরে, এটি সংশোধিত না হওয়া পর্যন্ত এর মান ধরে রাখে।
Vadiklk,
কেন ...? কারণ হ'ল স্থির পরিবর্তনশীল একবারে আরম্ভ করা হয় এবং পুরো প্রোগ্রাম জুড়ে এর মান বজায় থাকে maintain এর অর্থ, আপনি ফাংশন কলগুলির মধ্যে স্থির পরিবর্তনশীল ব্যবহার করতে পারেন। এছাড়াও এটি "একটি ফাংশনকে কতবার বলা হয়" গণনা করতে ব্যবহার করা যেতে পারে
main()
{
static int var = 5;
printf("%d ",var--);
if(var)
main();
}
এবং উত্তরটি 5 4 3 2 1 নয় এবং 5 5 5 5 5 5 নয় ... (অসীম লুপ) যেমনটি আপনি প্রত্যাশা করছেন। আবার কারণ হ'ল স্থিতিশীল পরিবর্তনশীল একবার শুরু করা হয়, যখন পরের বারের প্রধান () বলা হয় এটি 5 এ আরম্ভ হবে না কারণ এটি ইতিমধ্যে প্রোগ্রামে আরম্ভ করা হয়েছে o সুতরাং আমরা মানটি পরিবর্তন করতে পারি তবে পুনরায় নতুনকরণ করতে পারি না। স্থিতিশীল পরিবর্তনশীল কীভাবে কাজ করে তা স্থায়ী।
অথবা আপনি স্টোরেজ অনুযায়ী বিবেচনা করতে পারেন: স্ট্যাটিক ভেরিয়েবলগুলি কোনও প্রোগ্রামের ডেটা বিভাগে সংরক্ষণ করা হয় এবং ডেটা বিভাগে সঞ্চিত ভেরিয়েবলগুলি একবার শুরু করা হয়। এবং আরম্ভের আগে এগুলি বিএসএস বিভাগে রাখা হয়।
পরিবর্তে অটো (স্থানীয়) ভেরিয়েবলগুলি স্ট্যাকের মধ্যে সংরক্ষণ করা হয় এবং স্ট্যাকের সমস্ত ভেরিয়েবলগুলি সমস্ত সময় পুনরায় পুনঃনির্মাণ করা হয় যখন ফাংশনটিকে নতুন এফএআর (ফাংশন অ্যাক্টিভেশন রেকর্ড) বলা হয় তার জন্য তৈরি করা হয়।
আরও বোঝার জন্য ঠিক আছে, উপরের উদাহরণটি "স্ট্যাটিক" ছাড়াই করুন এবং আউটপুটটি কী হবে তা আপনাকে জানান। এটি আপনাকে এই দুটিয়ের মধ্যে পার্থক্য বুঝতে সাহায্য করে।
ধন্যবাদ জাভেদ
আসুন আমরা কেবল স্ট্যাটিক ভেরিয়েবলগুলি সম্পর্কিত উইকিপিডিয়া নিবন্ধটি পড়ি ...
স্ট্যাটিক লোকাল ভেরিয়েবলস: কোনও ফাংশনের অভ্যন্তরে স্থির হিসাবে ঘোষিত ভেরিয়েবলগুলি স্বয়ংক্রিয় স্থানীয় ভেরিয়েবলগুলির মতো একই সুযোগ থাকা অবস্থায় স্থিরভাবে বরাদ্দ করা হয়। সুতরাং ফাংশনটিকে আবার কল করার সময় ফাংশনটি তার স্থিতিশীল স্থানীয় ভেরিয়েবলগুলিতে যে পরিমাণ মূল্য দেয় তা এখনও উপস্থিত থাকবে।
সহজেই পরীক্ষিত হিসাবে আপনি 6 printed মুদ্রিত পাবেন এবং এর কারণ এখানে রয়েছে: যখন foo
প্রথম বলা হয় তখন স্ট্যাটিক ভেরিয়েবল এক্সটি শুরু করা হয় 5 Then
এখন পরবর্তী কল জন্য foo
। প্রোগ্রামটি স্ট্যাটিক ভেরিয়েবল ইনিশিয়ালাইজেশন এড়িয়ে যায় এবং এর পরিবর্তে value মানটি ব্যবহার করে যা সর্বশেষে x কে নির্ধারিত হয়েছিল। এক্সিকিউশনটি স্বাভাবিক হিসাবে এগিয়ে যায়, আপনাকে 7 মান দেয়।
And এবং Because কারণ স্থায়ী পরিবর্তনশীল অন্তর্বর্তীকরণ কেবল একবার, সুতরাং 5++ প্রথম কল এ 6 হয় 6++ দ্বিতীয় কল এ 7 হয় নোট-যখন 2 য় কল আসে তখন এটি 5 এর পরিবর্তে 6 মানের হয় কারণ x স্থির পরিবর্তনশীল।
কমপক্ষে সি ++ এ, যখন স্থানীয় স্ট্যাটিক ভেরিয়েবলটি সূচনা করতে ব্যবহৃত অভিব্যক্তিটি কোনও 'কনস্টেক্সপ্র' নয় (সংকলক দ্বারা মূল্যায়ন করা যায় না), তখন ফাংশনটিতে প্রথম কল করার সময় সূচনা অবশ্যই হওয়া উচিত। সবচেয়ে সহজ উদাহরণ হ'ল স্থানীয় স্ট্যাটিক ভেরিয়েবলটি অন্তর্নিহিত করার জন্য প্যারামিটারটি সরাসরি ব্যবহার করা। সুতরাং এই সংকলকটি অবশ্যই কলটি প্রথম নির্ধারণ করতে হবে কিনা তা অনুমান করার জন্য কোড নির্গত করতে হবে, যার পরিবর্তে স্থানীয় বুলিয়ান পরিবর্তনশীল প্রয়োজন। আমি এই জাতীয় উদাহরণটি সংকলন করেছি এবং পরীক্ষা করেছি যা সমাবেশ কোড দেখে সত্য is উদাহরণটি এর মতো হতে পারে:
void f( int p )
{
static const int first_p = p ;
cout << "first p == " << p << endl ;
}
void main()
{
f(1); f(2); f(3);
}
অবশ্যই, যখন এক্সপ্রেসনটি 'কনস্টেক্সপ্র' হয়, তখন এটি প্রয়োজন হয় না এবং আউটপুট অ্যাসেম্বলি কোডে সংকলক দ্বারা সঞ্চিত একটি মান ব্যবহার করে প্রোগ্রামের লোডে ভেরিয়েবলটি আরম্ভ করা যায়।