আকার (x ++) কেন ইনক্রিমেন্ট এক্স নয়?


505

এখানে দেব সি ++ উইন্ডোতে সংকলিত কোডটি দেওয়া হয়েছে:

#include <stdio.h>

int main() {
    int x = 5;
    printf("%d and ", sizeof(x++)); // note 1
    printf("%d\n", x); // note 2
    return 0;
}

আমি নোট 1x কার্যকর করার পরে 6 হবে আশা করি । তবে আউটপুটটি হ'ল:

4 and 5

নোট 1 এরx পরে বর্ধন কেন হয় না কেউ ব্যাখ্যা করতে পারেন ?


37
আমি নোট করব যে ডিভিসি ++ খুব পুরানো পুরানো সংকলক ব্যবহার করে, আপনি কোনও নতুন আইডিইতে আপগ্রেড করতে চাইতে পারেন, যেমন কোডব্লকস এক্সিলিপ বা ভিজ্যুয়াল স্টুডিও
টম জে নওয়েল

4
++ এক্স এক্স ++, সাইগউইন এবং জিসিসি 3.4.4 এর সমান ফলাফল উত্পাদন করে।
ইয়াহানান

6
@ টিম প্লেটজকার কারণ প্রথম মানটি ভেরিয়েবলের আকার, এবং ভেরিয়েবল নিজেই নয়।
সার্ফবাটলার

আমার উত্তরটি এইটির সাথে একীভূত হওয়ার কারণে যুক্ত করা হয়েছিল আমার উত্তরটি আসলে দেখায় যে আপনি কীভাবে রান-টাইম মূল্যায়ন পেতে পারেন VLAsযার ক্ষেত্রে অন্যদের কেউই করেন না।
শফিক ইয়াঘমোর

2
এই জাতীয় লেখা এড়ানো উচিত কারণ এটি অনাকাঙ্ক্ষিত পার্শ্ব প্রতিক্রিয়া হতে পারে। আপনার প্রশ্ন ইতিমধ্যে তাদের মধ্যে একটি।
ব্যবহারকারী 666412

উত্তর:


537

থেকে C99 স্ট্যান্ডার্ড (জোর খনি হয়)

6.5.3.4/2

মাপের অপারেটরটি তার অপারেন্ডের আকার (বাইটে) দেয়, যা কোনও প্রকারের এক্সপ্রেশন বা প্রথমত নাম হতে পারে। আকারটি অপারেন্ডের ধরণ থেকে নির্ধারিত হয়। ফলাফল একটি পূর্ণসংখ্যা হয়। অপারেন্ডের ধরণ যদি একটি পরিবর্তনশীল দৈর্ঘ্যের অ্যারে প্রকার হয় তবে অপারেন্ডকে মূল্যায়ন করা হয়; অন্যথায় অপারেন্ডকে মূল্যায়ন করা হয় না এবং ফলাফলটি পূর্ণসংখ্যার ধ্রুবক হয়।


51
"অপারেন্ডের ধরণটি যদি একটি পরিবর্তনশীল দৈর্ঘ্যের অ্যারে প্রকার হয় তবে অপারেন্ডকে মূল্যায়ন করা হয়" বাহ! আমি কখনই বুঝতে পারি নি
Kos

6
পরিবর্তনশীল দৈর্ঘ্যের অ্যারের প্রকার বলতে কী বোঝ? তার মানে অপারেন্ড একটি অ্যারে? এই ক্ষেত্রে কোডটি একটি অ্যারে নয়। আপনি কি আমার জন্য জিনিস পরিষ্কার করতে পারেন?
নিগাইল আর নভাল

37
একটি পরিবর্তনশীল দৈর্ঘ্যের অ্যারে সংকলনের সময় আকারটি অজানা হিসাবে ঘোষিত একটি অ্যারে হয়, উদাহরণস্বরূপ, আপনি Nস্টিডিন থেকে পড়েন এবং তৈরি করেন int array[N]। এটি সি 99+ এর মধ্যে একটি বৈশিষ্ট্য, সি ++ এ অনুপলব্ধ।
কোস

21
@ লিজেন্ডোফ কেজ, বিশেষত এর অর্থ হ'ল কিছু sizeof(int[++x])(সত্যই সত্যই একটি খারাপ ধারণা, যাইহোক) এর ++মূল্যায়ন করা যেতে পারে।
জেনস গুস্ট্ট

3
@ জো র্রেছনিগ: এটি মূল্যায়ন করেছেন gcc, clangএবং আদর্শের উপর
পিএফ

190

sizeofএকটি সংকলন-সময় অপারেটর , সুতরাং সংকলনের সময় sizeofএবং এর অপারেন্ড ফলাফল মান দ্বারা প্রতিস্থাপিত হয়। প্রতীক হয় মূল্যায়ন এ সব (যখন এটি একটি পরিবর্তনশীল দৈর্ঘ্য অ্যারে ব্যতীত); শুধুমাত্র টাইপ ফলাফলের গুরুত্বপূর্ণ।

short func(short x) {  // this function never gets called !!
   printf("%d", x);    // this print never happens
   return x;
}

int main() {
   printf("%d", sizeof(func(3))); // all that matters to sizeof is the 
                                  // return type of the function.
   return 0;
}

আউটপুট:

2

shortআমার মেশিনে 2 বাইট দখল হিসাবে

ফাংশনের রিটার্নের ধরন এতে পরিবর্তন করা হচ্ছে double:

double func(short x) {
// rest all same

8আউটপুট হিসাবে দেবে ।


12
শুধুমাত্র কখনও কখনও - এটি সম্ভব হলে সংকলন সময়।
মার্টিন বেকেট

10
-1, যেমন এটি গৃহীত (এবং সঠিক) উত্তরের সাথে মতবিরোধে রয়েছে, এবং মানটিকে উদ্ধৃত করে না।
সাম হোচেভার

1
স্ট্রিংয়ের সাথে কাজ করার সময় মাপের () অপারেটরের টাইম রেজোলিউশন সংকলনের একটি দুর্দান্ত সুবিধা রয়েছে। আপনার যদি স্ট্রিং থাকে যা স্ট্রেন () ব্যবহারের পরিবর্তে কোটড স্ট্রিং হিসাবে শুরু হয়, যেখানে স্ট্রিং সমন্বিত অক্ষর অ্যারেটি রান সময় নাল-টার্মিনেটরের জন্য স্ক্যান করতে হয়, মাপের (উদ্ধৃতি_আরক্ষক) সংকলন সময়ে জানা যায়, আর তাই রান-টাইমে। এটি একটি ছোট জিনিস, তবে আপনি যদি উদ্ধৃত স্ট্রিংটি কয়েক মিলিয়ন এবং মিলিয়ন বার লুপে ব্যবহার করেন তবে এটি কার্য সম্পাদনে উল্লেখযোগ্য পার্থক্য আনবে।
ব্যবহারকারী 2548100

আপনি যদি সত্যিই এটি লুপে লক্ষ লক্ষ লক্ষ বার ব্যবহার করেন তবে লুপের বাইরে দৈর্ঘ্যের গণনাটি ফ্যাক্ট করা আরও বেশি বুদ্ধিমানের কাজ নয় কি? আমি অবশ্যই আশা করি আপনার কোডটিতে কয়েক মিলিয়ন এবং কয়েক মিলিয়ন বিভিন্ন হার্ডকডযুক্ত ধ্রুবক নেই। : -ও
ভিকি

47

sizeof(foo) সংকলনের সময় একটি অভিব্যক্তির আকার আবিষ্কার করার জন্য সত্যই চেষ্টা করে:

6.5.3.4:

মাপের অপারেটরটি তার অপারেন্ডের আকার (বাইটে) দেয়, যা কোনও প্রকারের এক্সপ্রেশন বা প্রথমত নাম হতে পারে। আকারটি অপারেন্ডের ধরণ থেকে নির্ধারিত হয়। ফলাফল একটি পূর্ণসংখ্যা হয়। অপারেন্ডের ধরণ যদি একটি পরিবর্তনশীল দৈর্ঘ্যের অ্যারে প্রকার হয় তবে অপারেন্ডকে মূল্যায়ন করা হয়; অন্যথায় অপারেন্ডকে মূল্যায়ন করা হয় না এবং ফলাফলটি পূর্ণসংখ্যার ধ্রুবক হয়।

সংক্ষেপে: চলক দৈর্ঘ্যের অ্যারে, রানটাইম চালানো। : (নোট চলক দৈর্ঘ্য অ্যারেগুলির - অ্যারে সঙ্গে বরাদ্দ না কোনো নির্দিষ্ট বৈশিষ্ট্য আছে malloc(3)তা না হলে, শুধুমাত্র।) টাইপ মত প্রকাশের নির্ণয় করা হয়, এবং যে সময় সঙ্কলন করেন।


33

sizeofএকটি কম্পাইল-টাইম builtin অপারেটর এবং হয় না একটি ফাংশন। এটি প্রথম ক্ষেত্রে যখন বন্ধনী ছাড়াই আপনি এটি ব্যবহার করতে পারেন তখন এটি খুব স্পষ্ট হয়ে যায়:

(sizeof x)  //this also works

1
তবে এই প্রশ্নের উত্তর কীভাবে?
সেবাস্তিয়ান মাচ

5
@ ফ্রেসনেল: এটি কেবল এটি পরিষ্কার করার জন্য যে আকারটি "অদ্ভুত" এবং সাধারণ ফাংশনগুলির নিয়মের সাপেক্ষে নয়। (+) এবং (-)
হুগমগ

sizeofঅপারেটর না একটি কম্পাইল-টাইম অপারেটর, আপনি শুধুমাত্র একটি VLA দিতে এই জিনিসটা করতে হবে।
প্যাক্সিডিয়াবল

21

বিঃদ্রঃ

এই উত্তরটি একটি সদৃশ থেকে মার্জ করা হয়েছে, যা দেরী তারিখটি ব্যাখ্যা করে।

মূল

পরিবর্তনশীল দৈর্ঘ্যের অ্যারে আকার ব্যতীত এর তর্কগুলি মূল্যায়ন করে না। আমরা খসড়া সি 99 স্ট্যান্ডার্ড বিভাগ থেকে এটি দেখতে পাচ্ছি 6.5.3.4 আকারের অপারেটর অনুচ্ছেদ 2 যা বলে:

মাপের অপারেটরটি তার অপারেন্ডের আকার (বাইটে) দেয়, যা কোনও প্রকারের এক্সপ্রেশন বা প্রথমত নাম হতে পারে। আকারটি অপারেন্ডের ধরণ থেকে নির্ধারিত হয়। ফলাফল একটি পূর্ণসংখ্যা হয়। অপারেন্ডের ধরণ যদি একটি পরিবর্তনশীল দৈর্ঘ্যের অ্যারে প্রকার হয় তবে অপারেন্ডকে মূল্যায়ন করা হয়; অন্যথায় অপারেন্ডকে মূল্যায়ন করা হয় না এবং ফলাফলটি পূর্ণসংখ্যার ধ্রুবক হয়।

একটি মন্তব্য ( এখন সরানো হয়েছে ) জিজ্ঞাসা করা হয়েছে যে রান-টাইমে এর মতো কোনও কিছুর মূল্যায়ন হবে:

sizeof( char[x++]  ) ;

এবং প্রকৃতপক্ষে এটি হবে, এরকম কিছু কাজ করবে ( উভয়কে লাইভ দেখুন ):

sizeof( char[func()]  ) ;

যেহেতু তারা উভয় পরিবর্তনশীল দৈর্ঘ্যের অ্যারে হয়। যদিও, আমি কোনও একটিতে খুব বেশি ব্যবহারিক ব্যবহার দেখছি না।

দ্রষ্টব্য, পরিবর্তনশীল দৈর্ঘ্যের অ্যারেগুলি খসড়া C99 স্ট্যান্ডার্ড বিভাগে 6.7.5.2 অ্যারে ডিক্লেয়ারগুলি অনুচ্ছেদ 4 এ আচ্ছাদিত রয়েছে :

[...] যদি আকারটি একটি পূর্ণসংখ্যক ধ্রুবক প্রকাশ হয় এবং উপাদান ধরণের একটি ধ্রুব আকার থাকে তবে অ্যারের প্রকারটি একটি পরিবর্তনশীল দৈর্ঘ্যের অ্যারে প্রকার নয়; অন্যথায়, অ্যারে টাইপ একটি পরিবর্তনশীল দৈর্ঘ্যের অ্যারে প্রকার।

হালনাগাদ

সি 11-এ ভিএলএ ক্ষেত্রে উত্তর পরিবর্তন হয়, কিছু ক্ষেত্রে আকারের অভিব্যক্তি মূল্যায়ন করা হয় কিনা তা অনির্দিষ্ট। বিভাগের 6.7.6.2 অ্যারে ঘোষকগণ যা থেকে বলেছেন:

[...] যেখানে একটি আকারের এক্সপ্রেশন একটি আকারের অপারেটরের অপারেন্ডের অংশ এবং আকারের এক্সপ্রেশনটির মান পরিবর্তন করা অপারেটরের ফলাফলকে প্রভাবিত করবে না, সেখানে আকারের অভিব্যক্তিটি মূল্যায়ন করা হয় কিনা তা অনির্দিষ্ট।

উদাহরণস্বরূপ, এই জাতীয় ক্ষেত্রে ( এটি সরাসরি দেখুন ):

sizeof( int (*)[x++] )

1
এখানে মনে রাখার জন্য গুরুত্বপূর্ণ বিষয়টি হ'ল বেশিরভাগ সময় sizeofকার্যকরভাবে একটি ম্যাক্রো - এটি কোড তৈরি করে না, তবে প্রত্যাশিত মানকে প্রাক্কলিত করে এবং সরাসরি কোডে জমা করে। উল্লেখ্য , সিবি 99 অবধি এই একমাত্র আচরণ ছিল , কারণ ভিবিএর অস্তিত্ব ছিল না (এই উত্তর না হওয়া পর্যন্ত আমি তাদের সম্পর্কে আসলে কখনও শুনিনি, বিশ্বাস করুন বা না!)
করলি ব্রিগম্যান

কোন দিক দিয়ে অভিব্যক্তির মান নির্ধারণ করা এবং নতুন অপারেটরের সাথে দুটোই স্বাভাবিক, তা নির্ধারণ করা ছাড়া অন্য যে কোনও কিছুর জন্য sizeof (char[x++]);মূল্য ব্যবহার করবে ? xx++x
সুপারক্যাট

@ ডাল ... ভুল, হ্যাঁ, আমি অবশ্যই 'ভিএলএ' বলতে চাইছিলাম :) শফিক - কেন রানটাইমে এগুলি মূল্যায়ন করবে? যেমন আমি বলেছিলাম, আমি কখনই ভিএলএস দেখিনি, তবে সংকলনের সময় সেগুলির প্রকারগুলি উভয়ই জানা যায়, তাই না?
করলি ব্রিগম্যান

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

@ শাফিক - আহ, ঠিক আছে, আমার ধারণা আমার বিভ্রান্তি আমি বুঝতে পারি নি যে আমি char[x++]কোনও ভিএলএর হয়। এটি char*আমার অজানা চোখের মতো কার্যকরভাবে দেখায় ।
করলি ব্রিগম্যান

11

sizeofঅপারেটরের অপারেন্ড যেমন মূল্যায়ন না করা হয়, আপনি এটি করতে পারেন:

int f(); //no definition, which means we cannot call it

int main(void) {
        printf("%d", sizeof(f()) );  //no linker error
        return 0;
}

অনলাইন ডেমো: http://ideone.com/S8e2Y

এটি হ'ল, fযদি sizeofকেবলমাত্র এটি ব্যবহৃত হয় তবে আপনাকে ফাংশনটি সংজ্ঞায়িত করতে হবে না । এই কৌশলটি বেশিরভাগ সি ++ টেমপ্লেট ধাতব প্রোগ্রামে ব্যবহৃত হয়, এমনকি সি ++ তেও অপারেন্ড sizeofমূল্যায়ন হয় না।

কেন এই কাজ করে? এটি কাজ করে কারণ sizeofঅপারেটর মান অনুযায়ী অপারেট করে না , পরিবর্তে এটি এক্সপ্রেশনের ধরণের উপর কাজ করে । সুতরাং আপনি যখন লিখবেন sizeof(f()), এটি এক্সপ্রেশনটির ধরণের উপর পরিচালিত হয় f()এবং যা ফাংশনটির রিটার্ন টাইপ ছাড়া কিছুই নয় f। রিটার্নের ধরণটি সর্বদা সমান, যদি কার্য সম্পাদন করে তবে ফাংশনটি কী মান দেয় তা বিবেচনা করে না।

সি ++ এ আপনি এটিও করতে পারেন:

struct A
{
  A(); //no definition, which means we cannot create instance!
  int f(); //no definition, which means we cannot call it
};

int main() {
        std::cout << sizeof(A().f())<< std::endl;
        return 0;
}

তবুও দেখে মনে হচ্ছে, sizeofআমি প্রথমে একটি উদাহরণ তৈরি করছি A, লিখে লিখে A(), এবং তারপরে fউদাহরণটি ফাংশনটি কল করে , লিখেছি A().f(), তবে এরকম কিছুই ঘটে না।

ডেমো: http://ideone.com/egPMi

এখানে আরও একটি বিষয় যা এর আরও কিছু আকর্ষণীয় বৈশিষ্ট্য ব্যাখ্যা করে sizeof:


10

সংকলনের সময় ফাঁসির ঘটনা ঘটতে পারে না। সুতরাং ++i/ i++হবে না। এছাড়াও sizeof(foo())ফাংশনটি কার্যকর করবে না তবে সঠিক ধরণটি ফিরবে।


2
" সংকলনের সময় ফাঁসির ঘটনা ঘটতে পারে না। " আপনার অর্থ কী?
কৌতূহলী

1
সংকলন কেবলমাত্র অবজেক্ট কোড তৈরি করবে ... ব্যবহারকারী বাইনারি কার্যকর করলেই অবজেক্ট কোডটি কার্যকর করা হবে। সংকলনের সময় আকারটি হওয়ায় আই ++ উইল বাড়ানো ভুল।
রাকেশ

" আকার হিসাবে সংকলনের সময় ঘটে " আপনার অর্থ: "যেমন sizeofএকটি সংকলন সময় ধ্রুবক অভিব্যক্তি"?
কৌতূহলী

প্রি-প্রসেসিংয়ের সময় "# ডাইফাইন" এর মতোই একই আকারের সংকলন সময়ে ঘটবে। সংকলনের সময় সমস্ত ধরণের তথ্য পাওয়া যায় তাই আকারের পরে মূল্যায়ন করা হয় এবং সংকলনের সময় এবং মান প্রতিস্থাপন করা হয়। আগেই @ এমএমজি দ্বারা "সি 99 স্ট্যান্ডার্ড থেকে" ইতিমধ্যে উল্লেখ করা হয়েছে।
রাকেশ

1
" যাও sizeof কম্পাইল সময়ে ঘটবে এমন কিছু বিষয় যা একটি পরিবর্তনশীল দৈর্ঘ্য অ্যারে নয় জন্য"
curiousguy

0

sizeofসংকলন সময়ে চালিত হয়, তবে x++কেবল রান-টাইমে মূল্যায়ন করা যায়। এটি সমাধানের জন্য, সি ++ স্ট্যান্ডার্ড আদেশ দেয় যে অপারেন্ডটি sizeofমূল্যায়ন করা হয় না। সি স্ট্যান্ডার্ড বলেছেন:

অপারেন্ডের ধরণ [এর sizeof] যদি একটি পরিবর্তনশীল দৈর্ঘ্যের অ্যারে প্রকার হয় তবে অপারেন্ডকে মূল্যায়ন করা হয়; অন্যথায় অপারেন্ডকে মূল্যায়ন করা হয় না এবং ফলাফলটি পূর্ণসংখ্যার ধ্রুবক হয়।


সি ++ তে কোনও ভিএলএ নেই।
এলএফ

-2

sizeof() অপারেটর কেবল ডেটা-টাইপের আকার দেয়, এটি অভ্যন্তরীণ উপাদানগুলির মূল্যায়ন করে না।


এটি মিথ্যা, sizeof()অপারেটর পুনরাবৃত্তভাবে কাজ করে এবং কোনও ধারক, শ্রেণি বা কাঠামোর সদস্য ইত্যাদির সমস্ত উপাদানগুলির বাইটগুলিতে আকার পাবে আপনি কয়েকটি সদস্যের সাথে একটি সাধারণ বর্গ তৈরি করে খুব সহজেই নিজেকে এটি প্রমাণ করতে পারেন এবং sizeof()এটি আহ্বান । (তবে, সেখানে যে কোনও পয়েন্টার রয়েছে সেটির আকারটি দেখতে পাবে না - কেবলমাত্র পয়েন্টারের আকার।) এটি সমস্ত সংকলনের সময়ে ঘটেছিল, যেমন অন্যান্য মন্তব্যকারীরা বলেছিলেন: এর অভ্যন্তরের মত প্রকাশের sizeof()মূল্যায়ন হয় না।
টাইলার শেলবার্গ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.