"স্ট্যাটিক কনস্ট" বনাম "# ডেফাইন" বনাম "এনুম"


585

সি এর নীচের বিবৃতিগুলির মধ্যে কোনটি ব্যবহার করা ভাল?

static const int var = 5;

অথবা

#define var 5

অথবা

enum { var = 5 };

35
মজার বিষয় হল, এটি প্রায় স্ট্যাকওভারফ্লো / প্রশ্নগুলি / ১63৩73৩৩৩৩ / স্ট্যাটিক-কনস্ট- ভিএস- ডিফাইন হিসাবে একই প্রশ্ন । পার্থক্য কেবল এই যে প্রশ্নটি সি ++ সম্পর্কিত, এবং এটি একটি সি সম্পর্কে Since যেহেতু আমার উত্তরটি সি ++ নির্দিষ্ট ছিল, তাই আমি বলি যে এটি অভিন্ন নয়, তবে অন্যরাও এতে দ্বিমত পোষণ করতে পারে।
টেড

53
অভিন্ন নয়, অবশ্যই। এমন অনেকগুলি অঞ্চল রয়েছে যেখানে সি ++ সামঞ্জস্যতার কারণে সি সিনট্যাক্সের অনুমতি দেয়। এই ক্ষেত্রে, "এক্স করার সর্বোত্তম উপায় কী" এর মতো প্রশ্নের সি ++ তে বিভিন্ন উত্তর থাকবে। উদাহরণস্বরূপ অবজেক্টের সূচনা।
এমসাল্টারস


এটি কীভাবে মতামত ভিত্তিক নয়? তাদের প্রত্যেকের একটি আলাদা উদ্দেশ্য রয়েছে
স্যাম হ্যাম্মি

1
@ রবার্টসম্পোর্টস মনিকাসেলিও, হ্যাঁ তদন্তের জন্য আপনাকে ধন্যবাদ
বিজয়

উত্তর:


690

এটি আপনার মূল্য কী প্রয়োজন তার উপর নির্ভর করে। আপনি (এবং এখনও পর্যন্ত প্রত্যেকে) তৃতীয় বিকল্প বাদ দিয়েছেন:

  1. static const int var = 5;
  2. #define var 5
  3. enum { var = 5 };

নামের পছন্দ সম্পর্কে বিষয়গুলি উপেক্ষা করা, তারপরে:

  • যদি আপনার চারপাশে কোনও পয়েন্টার পাস করার প্রয়োজন হয় তবে আপনাকে অবশ্যই ব্যবহার করতে হবে (1)।
  • (2) যেহেতু আপাতদৃষ্টিতে একটি বিকল্প তাই আপনার চারপাশে পয়েন্টারগুলি পাস করার দরকার নেই।
  • (1) এবং (3) উভয়েরই ডিবাগারের প্রতীক টেবিলটিতে একটি চিহ্ন রয়েছে - এটি ডিবাগিংকে আরও সহজ করে তোলে। এটি সম্ভবত সম্ভবত (2) এর প্রতীক না থাকায় এটি কী তা ভাবছেন leaving
  • (1) বৈশ্বিক সুযোগে অ্যারেগুলির একটি মাত্রা হিসাবে ব্যবহার করা যায় না; (2) এবং (3) উভয়ই পারেন।
  • (1) ফাংশন সুযোগে স্থির অ্যারেগুলির একটি মাত্রা হিসাবে ব্যবহার করা যায় না; (2) এবং (3) উভয়ই পারেন।
  • C99 এর অধীনে, এগুলি সমস্ত স্থানীয় অ্যারে ব্যবহার করা যেতে পারে। প্রযুক্তিগতভাবে, (1) ব্যবহারের ফলে কোনও ভিএলএ (পরিবর্তনশীল দৈর্ঘ্যের অ্যারে) ব্যবহার বোঝানো হবে, যদিও 'ভার' দ্বারা বর্ণিত মাত্রা অবশ্যই 5 মাপে স্থির করা হবে।
  • (1) সুইচ স্টেটমেন্টের মতো জায়গায় ব্যবহার করা যাবে না; (2) এবং (3) উভয়ই পারেন।
  • (1) স্ট্যাটিক ভেরিয়েবল আরম্ভ করতে ব্যবহার করা যাবে না; (2) এবং (3) উভয়ই পারেন।
  • (২) আপনি যে কোডটি পরিবর্তন করতে চাননি তা পরিবর্তন করতে পারে কারণ এটি প্রিপ্রসেসর ব্যবহার করে; (1) এবং (3) উভয়ের এর মতো অপ্রত্যাশিত পার্শ্ব প্রতিক্রিয়া হবে না।
  • (2) প্রিপ্রোসেসরে সেট করা হয়েছে কিনা তা আপনি সনাক্ত করতে পারেন; (1) বা (3) এরও অনুমতি দেয় না।

সুতরাং, বেশিরভাগ প্রসঙ্গে, বিকল্পগুলির চেয়ে 'এনাম' পছন্দ করুন। অন্যথায়, প্রথম এবং শেষ বুলেট পয়েন্টগুলি নিয়ন্ত্রণকারী কারণ হতে পারে - এবং আপনার যদি উভয়কে একবারে সন্তুষ্ট করতে হয় তবে আপনাকে আরও কঠোরভাবে চিন্তা করতে হবে।

আপনি যদি সি ++ সম্পর্কে জিজ্ঞাসা করছিলেন, তবে আপনি প্রতিবার স্ট্যাটিক কনস্ট - (1) বিকল্পটি ব্যবহার করবেন।


111
দুর্দান্ত তালিকা! এর একটি অসুবিধা enumহ'ল এগুলি int([C99] 6.7.2.2/3) হিসাবে প্রয়োগ করা হয়েছে । এ #defineআপনাকে স্বাক্ষরবিহীন এবং দীর্ঘ Uএবং Lপ্রত্যয়গুলি নির্দিষ্ট constকরতে দেয় এবং আপনাকে একটি প্রকার দিতে দেয়। enumসাধারণ ধরণের রূপান্তরগুলির সাথে সমস্যা তৈরি করতে পারে।
গৌথির

37
(২) লোকেরা সুরক্ষার বিষয়ে সর্বদা অভিযোগ করে। আমি কখনই বুঝতে পারি না কেন কেবল "# ডেফাইন ভার ((প্রাক্তন 5))" ব্যবহার করবেন না এবং হররে আপনি কোনও সংজ্ঞায়িত সহ সুরক্ষা পেয়েছেন।
ইনগো ব্ল্যাকম্যান

6
@ রেডএক্স: স্থান উদ্বেগের জন্য আপনাকে খুব অদ্ভুত পরিবেশে থাকতে হবে। এটি বলেছে যে, অতিরিক্ত প্রতিটি জায়গাতেই অতিরিক্ত স্থান ব্যবহার করবে enumনা #define। তথ্য বিভাগে বা হিপ বা স্ট্যাকের স্টোরেজ বরাদ্দ না করে মানটি নির্দেশের অংশ হিসাবে অবজেক্ট কোডে উপস্থিত হবে। আপনার জন্য কিছু জায়গা বরাদ্দ থাকবে static const int, তবে আপনি যদি কোনও ঠিকানা না নেন তবে সংকলকটি এটি অপ্টিমাইজ করতে পারে।
জোনাথন লেফলার

15
enumগুলি (এবং static const) এর জন্য অন্য একটি 'ভোট' : সেগুলি পরিবর্তন করা যায় না। একটি যেখানে 'd' দেওয়া defineযেতে পারে এবং #undefineসেখানে দেওয়া মানের সাথে স্থির থাকে। enumstatic const
টিমারের

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

282

সাধারণভাবে বলতে:

static const

কারণ এটি সুযোগকে সম্মান করে এবং টাইপ-নিরাপদ।

আমি কেবলমাত্র ক্যাভিয়েট দেখতে পেলাম: আপনি যদি ভেরিয়েবলটি সম্ভবত কমান্ড লাইনে সংজ্ঞায়িত করতে চান তবে। এখনও একটি বিকল্প আছে:

#ifdef VAR // Very bad name, not long enough, too general, etc..
  static int const var = VAR;
#else
  static int const var = 5; // default value
#endif

যখনই সম্ভব, ম্যাক্রোগুলি / উপবৃত্তির পরিবর্তে, একটি টাইপ-নিরাপদ বিকল্প ব্যবহার করুন।

যদি আপনি সত্যিই কোনও ম্যাক্রোর সাথে যেতে চান (উদাহরণস্বরূপ, আপনি চান __FILE__বা __LINE__), তবে আপনি আপনার ম্যাক্রোর খুব ভালভাবে নাম লিখবেন : এর নামকরণ কনভেনশনে বুস্ট প্রকল্পের নাম দিয়ে শুরু করে সমস্ত উচ্চ-মামলার প্রস্তাব দেয় (এখানে BOOST_ ), গ্রন্থাগারটি বন্ধ করার সময় আপনি লক্ষ্য করবেন যে এটি (সাধারণত) নির্দিষ্ট অঞ্চলের নাম (লাইব্রেরি) এর পরে অর্থবহ নাম সহ রয়েছে।

এটি সাধারণত দীর্ঘ নামগুলি তৈরি করে :)


2
সম্মত - প্রিপ্রসেসর সিন্ট্যাক্স সম্পর্কে সচেতন না হওয়ায় # নির্ধারিত ম্যাঙ্গিলিং কোডের একটি সাধারণ বিপদ রয়েছে।
নিলডুরান্ট

10
#Ifdef এর চেয়ে #if ব্যবহার করা আরও ভাল তবে অন্যথায় আমি সম্মত। +1 টি।
টিম পোস্ট

58
এটি স্ট্যান্ডার্ড সি ++ ধর্ম প্রচার ev বিকল্পগুলি কী এবং কী তা বোঝাতে নীচের উত্তরটি আরও পরিষ্কার। বিশেষত: আমার সবেমাত্র "স্ট্যাটিক কনস্ট" সমস্যা ছিল। কেউ এটির শিরোনামের ফাইলে প্রায় 2000 "ধ্রুবক" সংজ্ঞায়িত করতে ব্যবহার করেছেন। তারপরে এই শিরোলেখ ফাইলটি প্রায় 100 ".c" এবং ".cpp" ফাইলগুলিতে অন্তর্ভুক্ত ছিল। => "কনসেট" এর জন্য 8 এমবিটিস। গ্রেট। হ্যাঁ আমি জানি যে আপনি অযৌক্তিক কনসটেন্টগুলি অপসারণ করতে কোনও লিঙ্কার ব্যবহার করতে পারেন তবে এটি আপনাকে এখনও ছেড়ে দেয় যা "কনসেন্টস" যা রেফারেন্সযুক্ত। এই উত্তরের সাথে দোষত্রুটির কিছুই নেই।
ইনগো ব্ল্যাকম্যান

2
@ ইঙ্গো ব্ল্যাকম্যান: একটি ভাল সংকলক সহ, staticযাদের ঠিকানা নেওয়া হয়েছে কেবল তারাই থাকবে; এবং যদি ঠিকানাটি নেওয়া হয় তবে তারা একটি #defineবা enum(কোনও ঠিকানা) ব্যবহার করতে পারত না ... সুতরাং বিকল্পটি কী ব্যবহার করতে পারত তা আমি সত্যিই ব্যর্থ হয়েছি। আপনি যদি "সংকলনের সময় মূল্যায়ন" দিয়ে কিছু করতে পারেন তবে আপনি extern constতার পরিবর্তে সন্ধান করতে পারেন ।
ম্যাথিউ এম।

15
@ টিম পোস্ট: বুলিয়ান পতাকাগুলির #ifচেয়ে বেশি পছন্দনীয় হতে পারে #ifdef, তবে এক্ষেত্রে কমান্ড লাইন থেকে এটি নির্ধারণ varকরা অসম্ভব হয়ে উঠবে 0। সুতরাং এই ক্ষেত্রে, #ifdefযতক্ষণ না 0আইনী মূল্য হিসাবে ততক্ষণ তা বোঝা যায় var
মার্টেন

108

সি তে, বিশেষভাবে? সিতে সঠিক উত্তরটি হ'ল: #define(অথবা উপযুক্ত হলে ব্যবহার করুন enum)

যদিও কোনও constবস্তুর স্কোপিং এবং টাইপিংয়ের বৈশিষ্ট্য থাকা সুবিধাজনক তবে বাস্তবে constসিতে থাকা বস্তুগুলি (সি ++ এর বিপরীতে) সত্য ধ্রুবক নয় এবং তাই বেশিরভাগ ব্যবহারিক ক্ষেত্রে সাধারণত অকেজো হয়।

সুতরাং, সিতে পছন্দটি নির্ধারণ করা উচিত আপনি কীভাবে আপনার ধ্রুবকটি ব্যবহার করার পরিকল্পনা করছেন। উদাহরণস্বরূপ, আপনি কোনও const intবস্তুকে caseলেবেল হিসাবে ব্যবহার করতে পারবেন না (যখন ম্যাক্রো কাজ করবে)। আপনি কোনও const intবিষয়টিকে বিট-ফিল্ড প্রস্থ হিসাবে ব্যবহার করতে পারবেন না (যখন ম্যাক্রো কাজ করবে)। C89 / 90 এ আপনি constকোনও অ্যারের আকার নির্দিষ্ট করতে কোনও বস্তু ব্যবহার করতে পারবেন না (যখন ম্যাক্রো কাজ করবে)। এমনকি C99 এ আপনি constযখন বিন-ভিএলএ অ্যারে প্রয়োজন তখন কোনও অ্যারের আকার নির্দিষ্ট করতে কোনও অবজেক্ট ব্যবহার করতে পারবেন না ।

এটি যদি আপনার পক্ষে গুরুত্বপূর্ণ হয় তবে তা আপনার পছন্দটি নির্ধারণ করবে। বেশিরভাগ সময়, আপনার #defineসিতে ব্যবহার করা ছাড়া কোনও বিকল্প নেই এবং অন্য কোনও বিকল্প ভুলে যাবেন না, যা সিতে সত্যিকারের ধ্রুবক তৈরি করে enum

সি ++ constঅবজেক্টগুলিতে সত্যিকারের ধ্রুবক থাকে, সুতরাং সি ++ এ constভেরিয়েন্টটি পছন্দ করা প্রায় সর্বদা ভাল ( staticযদিও সি ++ তে স্পষ্ট করার প্রয়োজন নেই )।


6
"আপনি কেস লেবেল হিসাবে কোন কনট ইনট অবজেক্ট ব্যবহার করতে পারবেন না (যখন একটি ম্যাক্রো কাজ করবে)" ---> এই বক্তব্যটি সম্পর্কে আমি সুইচ-সিটিতে এটির ক্ষেত্রে একটি কনস্টেন্ট ভেরিয়েবল পরীক্ষা করেছি ....
জন

8
@ জোহান: ঠিক আছে, আপনার পরীক্ষা করা কোডটি নির্দিষ্ট করা উচিত এবং নির্দিষ্ট সংকলকটির নাম দিন। const intকেস-লেবেলে অবজেক্টগুলি ব্যবহার করা সি ভাষার সমস্ত সংস্করণে অবৈধ। (অবশ্যই, আপনার
সংকলকটি

11
"... এবং তাই বেশিরভাগ ব্যবহারিক ক্ষেত্রে সাধারণত অকেজো হয় " " আমি একমত নই আপনার নামটি ধ্রুবক অভিব্যক্তি হিসাবে ব্যবহার করার প্রয়োজন না থাকলে এগুলি পুরোপুরি কার্যকর। সি তে "ধ্রুবক" শব্দের অর্থ এমন কিছু যা সংকলনের সময়ে মূল্যায়ন করা যেতে পারে; constমানে কেবল পঠনযোগ্য। const int r = rand();পুরোপুরি আইনী।
কিথ থম্পসন

C ++, এটি ব্যবহার করার জন্য উত্তম constexprযেমন তুলনায় constসঙ্গে বিশেষভাবে stlমত পাত্রে arrayবা bitset
মায়ুখ সরকার

1
@ জোহান আপনি অবশ্যই switch()বিবৃতিতে পরীক্ষা করেছেন, caseএকটিতে নয়। আমি কেবল এটিরও ধরা পড়েছি
Hi

32

static constএবং এর মধ্যে পার্থক্যটি #defineহ'ল প্রাক্তন মেমরিটি ব্যবহার করে এবং পরে স্টোরেজটির জন্য মেমরিটি ব্যবহার করে না। দ্বিতীয়ত, আপনি কোনওটির ঠিকানা পাস করতে পারবেন না #defineতবে আপনি এ এর ​​ঠিকানাটি পাস করতে পারবেন static const। আসলে এটি নির্ভর করে যে আমরা কোন পরিস্থিতিতে আছি তার উপর নির্ভর করে, আমাদের এই দুটিয়ের মধ্যে একটি নির্বাচন করা দরকার। উভয়ই বিভিন্ন পরিস্থিতিতে তাদের সেরা। দয়া করে ধরে নিবেন না যে একজন অন্যটির চেয়ে ভাল ... :-)

যদি এমনটি হত, ডেনিস রিচি সেরাকে একা রেখে দিতেন ... হাহাহাহা ... :-)


6
মেমরিটি উল্লেখ করার জন্য +1, কিছু এম্বেড থাকা সিস্টেমে এখনও তেমন কিছু নেই, যদিও আমি সম্ভবত স্থির কনসেন্ট ব্যবহার শুরু করব এবং প্রয়োজনে কেবল # সংজ্ঞাতে পরিবর্তন করব।
fluffyben

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

2
ব্যবহারিকভাবে বলতে গেলে এটি সত্য (আর) নয় যে constকোনও স্মৃতি ব্যবহার করে। জিসিসি (৪.৩.৩ এবং কয়েকটি নতুন সংস্করণ দিয়ে পরীক্ষা করা) const int-O3 ব্যবহার করার সময় সহজেই আপনার কোডটিতে সরাসরি আক্ষরিক হয়ে যায়। সুতরাং আপনি যদি কম র‌্যাম এম্বেডড ডেভলপমেন্ট করেন (যেমন এভিআর) আপনি নিরাপদে সি কনসেটগুলি ব্যবহার করতে পারেন যদি আপনি জিসিসি বা অন্য কোনও সামঞ্জস্যপূর্ণ সংকলক ব্যবহার করেন। আমি এটি পরীক্ষা করে দেখিনি তবে কলং আশা করে বিটিডব্লিউ একই কাজ করবে।
রাফেল

19

সি #defineতে অনেক বেশি জনপ্রিয়। উদাহরণস্বরূপ অ্যারে আকারগুলি ঘোষণার জন্য আপনি এই মানগুলি ব্যবহার করতে পারেন:

#define MAXLEN 5

void foo(void) {
   int bar[MAXLEN];
}

আমার জানা মতে এএনএসআই সি আপনাকে static constএই প্রসঙ্গে ব্যবহার করতে দেয় না। সি ++ এ আপনার ক্ষেত্রে ম্যাক্রোগগুলি এড়ানো উচিত। তুমি লিখতে পারো

const int maxlen = 5;

void foo() {
   int bar[maxlen];
}

এমনকি এমনকি ছেড়ে চলে যান staticকারণ অভ্যন্তরীণ লিঙ্কেজ constইতিমধ্যে [কেবলমাত্র C ++ এ) দ্বারা জড়িত।


1
"অভ্যন্তরীণ সংযোগ" এর অর্থ কী? আমার const int MY_CONSTANT = 5;একটি ফাইল থাকতে পারে এবং extern const int MY_CONSTANT;অন্যটিতে এটি অ্যাক্সেস করতে পারি । আমি (অন্তত C99) মান যে কোন তথ্য খুঁজে পাইনি const": 5 একটি বস্তুর জন্য একটি identi ফাই Er ঘোষণা ফাই Le সুযোগ এবং কোন স্টোরেজ ক্লাসের সুনিন্টি ফাই Er পারবে, তবে তার দুটো ঘটনার বাহ্যিক 6.2.2" ডিফল্ট আচরণ পরিবর্তন।
গৌথিয়ার

@ গৌথির: দুঃখিত, সে সম্পর্কে আমার বলা উচিত ছিল "ইতিমধ্যে সি ++ ভাষায় কনস্টের দ্বারা নিহিত"। এটি সি ++ এর সাথে নির্দিষ্ট।
বিক্রয়বিটজে

এটা চমৎকার @sellibitze পথ ধরে কিছু আর্গুমেন্ট দেখতে পরিবর্তে টন মতামত যদি সত্য আর্গুমেন্ট জন্য বোনাস হবে, আপনি বুঝেছি!
পল

1
C99 হিসাবে, আপনার দ্বিতীয় স্নিপেট আইনী। barএকটি ভিএলএ (পরিবর্তনশীল দৈর্ঘ্যের অ্যারে); সংকলক সম্ভবত কোড জেনারেট করে যেমন এর দৈর্ঘ্য স্থির ছিল।
কিথ থম্পসন

14

constসি-তে আরেকটি অপূর্ণতা হ'ল আপনি আর কোনওটিকে আরম্ভ করার ক্ষেত্রে মানটি ব্যবহার করতে পারবেন না const

static int const NUMBER_OF_FINGERS_PER_HAND = 5;
static int const NUMBER_OF_HANDS = 2;

// initializer element is not constant, this does not work.
static int const NUMBER_OF_FINGERS = NUMBER_OF_FINGERS_PER_HAND 
                                     * NUMBER_OF_HANDS;

এমনকি এটি কোনও কনস্টের সাথে কাজ করে না যেহেতু সংকলক এটি ধ্রুবক হিসাবে দেখেনি:

static uint8_t const ARRAY_SIZE = 16;
static int8_t const lookup_table[ARRAY_SIZE] = {
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; // ARRAY_SIZE not a constant!

আমি constএই ক্ষেত্রে টাইপ ব্যবহার করতে পেরে খুশি হব , অন্যথায় ...


5
গেমটি থেকে একটু দেরি হলেও এই প্রশ্নটি উঠে এসেছিল আরও একটি প্রশ্নে। static uint8_t const ARRAY_SIZE = 16;হঠাৎ আপনার সমস্ত সংকলন আর কেন সংকলনগুলি কিছুটা চ্যালেঞ্জের হতে পারে তা অনুসরণ করে তাড়না করা, বিশেষত যখন #define ARRAY_SIZE 256হেডারগুলির জটলা ওয়েবের মধ্যে দশ স্তর গভীরভাবে সমাহিত করা হয়। সমস্ত ক্যাপের নাম ARRAY_SIZEঝামেলা চাইছে। ম্যাক্রোগুলির জন্য ALL_CAPS সংরক্ষণ করুন এবং ALL_CAPS আকারে নেই এমন ম্যাক্রো কখনই সংজ্ঞায়িত করবেন না।
ডেভিড হ্যামেন

@ ডেভিড: সঠিক পরামর্শ, যা আমি অনুসরণ করব।
গৌথিয়ার

1
4 বছর পরে আপনি কেন আমাকে "বাসা" করতে পারছেন না তা বুঝতে পেরে আপনি আমাকে অনেক সময় বাঁচিয়েছিলেন const। এটি আরও upvated হতে পারে!
প্লুফ

11

আপনি যদি এটির সাথে পালাতে পারেন তবে এর static constঅনেক সুবিধা রয়েছে। এটি সাধারণ স্কোপ নীতিগুলি মান্য করে, একটি ডিবাগারে দৃশ্যমান হয় এবং সাধারণত নিয়মগুলি মানায় যা ভেরিয়েবলগুলি পালন করে।

তবে কমপক্ষে মূল সি স্ট্যান্ডার্ডে এটি আসলে ধ্রুবক নয়। যদি আপনি ব্যবহার করেন তবে আপনি ঘোষণা হিসাবে #define var 5লিখতে পারেন int foo[var];, তবে আপনি এটি করতে পারবেন না (সংকলক এক্সটেনশন হিসাবে "সহ" static const int var = 5;এটি সি ++ তে নয়, যেখানে static constসংস্করণটি যে কোনও জায়গায় ব্যবহার করা যেতে পারে #define, এবং আমি এটি বিশ্বাস করি সি 99 এর ক্ষেত্রেও এটি।

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


6
দুর্ভাগ্যক্রমে, C99 এর ক্ষেত্রে এটি হয় না। constC99 এ এখনও সত্যিকারের ধ্রুবক নয়। আপনি constC99 এর সাথে অ্যারের আকার ঘোষণা করতে পারেন , তবে কেবলমাত্র C99 চলক দৈর্ঘ্যের অ্যারে সমর্থন করে। এই কারণে, এটি কেবলমাত্র যেখানে VLAs অনুমোদিত তা কাজ করবে। উদাহরণস্বরূপ, এমনকি সি 99 এ, আপনি এখনও constকোনও সদস্য অ্যারের আকার ঘোষণা করতে একটি ব্যবহার করতে পারবেন না struct
এএনটি

যদিও এটি সঠিক যে সি 99 আপনাকে এটি করতে দেয় না, জিসিসি (4.5.3 দিয়ে পরীক্ষা করা) আপনাকে পুরোপুরি কোনও const intআকারের সাথে অ্যারেগুলি শুরু করতে দেবে যেন এটি সি ++ কনস্ট বা ম্যাক্রো। আপনি যদি মান থেকে জিসিসির এই বিচ্যুতির উপর নির্ভর করতে চান তবে অবশ্যই আপনার পছন্দ, আপনি যদি জিসিসি বা ক্ল্যাংয়ের চেয়ে অন্য সংকলকটি ব্যবহার করে সত্যিই ফর্স করতে না পারেন তবে আমি ব্যক্তিগতভাবে এটির সাথে যাব, পরবর্তীটির এখানে একই বৈশিষ্ট্য রয়েছে (ক্ল্যাংয়ের সাথে পরীক্ষা করা হয়েছে) 3.7)।
রাফেল

7

এটি # ডিফাইন পরিবর্তে কনস্ট ব্যবহার করা সর্বদা পছন্দনীয়। এর কারণ কনস্টাইলারটি সংকলক এবং প্রিপ্রসেসর দ্বারা # ডিফাইন দ্বারা চিকিত্সা করা হয়। এটি # ডিফাইন নিজেই কোডের অংশ নয় (মোটামুটি কথা বলার মতো) is

উদাহরণ:

#define PI 3.1416

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

এই সমস্যাটি একটি প্রতীকী ডিবাগারেও উত্থিত হতে পারে, কারণ, আবার আপনি যে নামটির সাথে প্রোগ্রামিং করছেন সেটি প্রতীক টেবিলের মধ্যে নাও থাকতে পারে।

সমাধান:

const double PI = 3.1416; //or static const...

6

#define var 5আপনার মতো জিনিস থাকলে আপনাকে সমস্যা সৃষ্টি করবে mystruct.var

উদাহরণ স্বরূপ,

struct mystruct {
    int var;
};

#define var 5

int main() {
    struct mystruct foo;
    foo.var = 1;
    return 0;
}

প্রিপ্রসেসর এটি প্রতিস্থাপন করবে এবং কোডটি সংকলন করবে না। এই কারণে, traditionalতিহ্যবাহী কোডিং শৈলীতে সমস্ত ধ্রুবকগুলি #defineসংঘাত এড়ানোর জন্য বড় ধরণের অক্ষর ব্যবহার করার পরামর্শ দেয় ।


6

আমি একটি পার্থক্য প্রদর্শনের জন্য দ্রুত পরীক্ষা প্রোগ্রাম লিখেছি:

#include <stdio.h>

enum {ENUM_DEFINED=16};
enum {ENUM_DEFINED=32};

#define DEFINED_DEFINED 16
#define DEFINED_DEFINED 32

int main(int argc, char *argv[]) {

   printf("%d, %d\n", DEFINED_DEFINED, ENUM_DEFINED);

   return(0);
}

এটি এই ত্রুটিগুলি এবং সতর্কতার সাথে সংকলন করে:

main.c:6:7: error: redefinition of enumerator 'ENUM_DEFINED'
enum {ENUM_DEFINED=32};
      ^
main.c:5:7: note: previous definition is here
enum {ENUM_DEFINED=16};
      ^
main.c:9:9: warning: 'DEFINED_DEFINED' macro redefined [-Wmacro-redefined]
#define DEFINED_DEFINED 32
        ^
main.c:8:9: note: previous definition is here
#define DEFINED_DEFINED 16
        ^

নোট করুন যে এনাম একটি সংজ্ঞা দেয় যখন সংজ্ঞায়িত একটি সতর্কতা দেয়।


4

সংজ্ঞাটি

const int const_value = 5;

সর্বদা স্থির মান নির্ধারণ করে না। কিছু সংকলক (উদাহরণস্বরূপ tcc 0.9.26 ) "কনস্ট_ভ্যালু" নামের সাথে চিহ্নিত মেমরিটিকে কেবল বরাদ্দ করে। "কনস্ট_ভ্যালু" সনাক্তকারী ব্যবহার করে আপনি এই স্মৃতিটিকে পরিবর্তন করতে পারবেন না। তবে আপনি এখনও অন্য সনাক্তকারী ব্যবহার করে মেমরিটি পরিবর্তন করতে পারেন:

const int const_value = 5;
int *mutable_value = (int*) &const_value;
*mutable_value = 3;
printf("%i", const_value); // The output may be 5 or 3, depending on the compiler.

এর অর্থ সংজ্ঞা

#define CONST_VALUE 5

একটি ধ্রুবক মান সংজ্ঞায়নের একমাত্র উপায় যা কোনও উপায়ে পরিবর্তন করা যায় না।


8
পয়েন্টার ব্যবহার করে একটি ধ্রুবক মান পরিবর্তন করা অনির্ধারিত আচরণ। আপনি যদি সেখানে যেতে ইচ্ছুক হন, #defineমেশিন কোডটি সম্পাদনা করেও সংশোধন করা যায়।
উগ্রোরেন

আপনি আংশিক ঠিক বলেছেন। আমি ভিজ্যুয়াল স্টুডিও 2012 এর সাথে কোডটি পরীক্ষা করেছি এবং এটি মুদ্রণ করে 5। তবে #defineকোনওটি সংশোধন করতে পারে না কারণ এটি একটি প্রিপ্রেসেসর ম্যাক্রো। এটি বাইনারি প্রোগ্রামে বিদ্যমান নেই। যদি কেউ যেখানে CONST_VALUEব্যবহৃত সমস্ত জায়গাগুলি পরিবর্তন করতে চায় তবে একে একে একে একে করতে হয়েছিল।
ব্যবহারকারী 2229691

3
@ ইউগোরেন: ধরুন আপনি #define CONST 5তখন লেখেন , if (CONST == 5) { do_this(); } else { do_that(); }এবং সংকলকটি elseশাখাটি মুছে ফেলে । আপনি কীভাবে মেশিন কোডটি CONST6 এ পরিবর্তন করার প্রস্তাব দিচ্ছেন ?
কিথ থম্পসন

@ কিথথম্পসন, আমি কখনও বলিনি যে এটি সহজে এবং বিশ্বাসযোগ্যভাবে করা যায়। ঠিক এটি #defineবুলেট-প্রুফ নয়।
ugoren

3
@ ইউগোরেন: আমার বক্তব্যটি হ'ল "মেশিন কোডটি সম্পাদনা করা" এ এর ​​মান পরিবর্তনের প্রভাবটির সদৃশ করার কোনও বুদ্ধিমান উপায় নয় #define। এটি করার একমাত্র আসল উপায় হ'ল উত্স কোডটি সম্পাদনা করা এবং পুনরায় সংযোগ করা।
কিথ থম্পসন

4

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

পূর্ণসংখ্যার জন্য, আপনি খুব সীমাবদ্ধ মেমরির সাথে এম্বেড করা পরিবেশে থাকলে, ধ্রুবকটি কোথায় সংরক্ষণ করা হয় এবং কীভাবে এটিতে অ্যাক্সেস করা হয় তা কীভাবে সঙ্কলিত হয় তা নিয়ে আপনার চিন্তার প্রয়োজন হতে পারে। সংকলকটি রান সময়ে দুটি কনস্ট যুক্ত করতে পারে তবে সংকলনের সময় দুটি # সংজ্ঞা যুক্ত করতে পারে। একটি # নির্দিষ্ট ধ্রুবককে এক বা একাধিক এমওভি [তাত্ক্ষণিক] নির্দেশিকায় রূপান্তর করা যেতে পারে, যার অর্থ ধ্রুবকটি কার্যকরভাবে প্রোগ্রামের মেমোরিতে সংরক্ষিত থাকে। একটি কনস্ট কনস্ট্যান্ট ডেটা মেমরির .const বিভাগে সংরক্ষণ করা হবে। হার্ভার্ড আর্কিটেকচারযুক্ত সিস্টেমে কর্মক্ষমতা এবং মেমরির ব্যবহারের ক্ষেত্রে পার্থক্য থাকতে পারে, যদিও তারা সম্ভবত ছোট হবে be তারা অভ্যন্তরীণ লুপগুলির হার্ড-কোর অপ্টিমাইজেশনের জন্য গুরুত্বপূর্ণ হতে পারে।


3

"যা সর্বদা সেরা" এর মত উত্তর নেই তবে ম্যাথিউ বলেছিলেন বলে মনে করবেন না said

static const

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


1
"আপনি ভেরিয়েবলটি দেখতে পারবেন না" রাইট, এটি ভেরিয়েবল নয়। এটি পরিবর্তন হয় না, আপনার এটি দেখার দরকার কেন? এটি কেবলমাত্র লেবেল অনুসন্ধান করে ব্যবহার করা হয়েছে এটি সর্বত্র খুঁজে পেতে পারেন। কেন আপনি # নির্ধারণের জন্য (বা এমনকি চান) প্রয়োজন?
মার্শাল ইউবঙ্কস

3

ঘটনাচক্রে, এর বিকল্প #define, যা সঠিক স্কোপিং সরবরাহ করে তবে একটি "সত্য" ধ্রুবকের মতো আচরণ করে, তা হ'ল এনাম "। উদাহরণ স্বরূপ:

enum {number_ten = 10;}

অনেক ক্ষেত্রে, এটি গণনা করা ধরণের সংজ্ঞা এবং এই ধরণের ভেরিয়েবলগুলি তৈরি করতে দরকারী; যদি এটি হয়ে যায়, ডিবাগারগুলি তাদের গণনার নাম অনুসারে চলক প্রদর্শন করতে সক্ষম হতে পারে।

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


1
সি-তে, গণনার ধ্রুবকগুলি সর্বদা টাইপ থাকে int, সুতরাং "এনাম হ্যাক" অন্যান্য পূর্ণসংখ্যার প্রকারের সাথে ব্যবহার করা যায় না। (গণনাটি টাইপ কিছু প্রয়োগ-সংজ্ঞায়িত পূর্ণসংখ্যার ধরণের সাথে সামঞ্জস্যপূর্ণ, প্রয়োজনীয়ভাবে নয় int, তবে এই ক্ষেত্রে প্রকারটি বেনামে যাতে কোনও ব্যাপার না))
কীথ থমসন

@ কিথথম্পসন: যেহেতু আমি উপরেরটি লিখেছি, আমি পড়েছি যে মাইক্রা-সি বিভক্ত হবে যদি একটি সংকলক একটি অঙ্ক-টাইপযুক্ত intভেরিয়েবল (যা সংকলকগুলি করার অনুমতি দেয়) ব্যতীত অন্য কোনও ধরণের কাজ নির্ধারণ করে এবং একজন এই জাতীয় একটি ভেরিয়েবলের জন্য নিযুক্ত করার চেষ্টা করে নিজস্ব গণনার সদস্য। আমি আশা করি মানক কমিটিগুলি নির্দিষ্ট শব্দার্থক দিয়ে পূর্ণসংখ্যার প্রকার ঘোষণার বহনযোগ্য উপায় যুক্ত করবে। যে কোনও প্ল্যাটফর্ম, charআকার নির্বিশেষে , উদাহরণস্বরূপ এমন কোনও প্রকারের ঘোষণা করতে সক্ষম হওয়া উচিত যা মোড 65536 মোড়বে, এমনকি সংকলকটিতে প্রচুর পরিমাণে AND R0,#0xFFFFবা সমতুল্য নির্দেশাবলী যুক্ত করতে হবে।
সুপারক্যাট

আপনি ব্যবহার করতে পারেন uint16_t, যদিও এটি অবশ্যই একটি গণনার ধরণ নয়। এটা তোলে ব্যবহারকারী পূর্ণসংখ্যা একটি প্রদত্ত পরিগণনা প্রকার প্রতিনিধিত্ব করতে ব্যবহৃত টাইপ উল্লেখ করা যাক চমৎকার হবে, কিন্তু আপনি একটি সঙ্গে একই প্রভাব অনেক অর্জন করতে পারেন typedefজন্য uint16_tএবং একটি সিরিজ #defineপৃথক মানের জন্য গুলি।
কিথ থম্পসন

1
@ কিথথম্পসন: আমি বুঝতে পেরেছি যে historicalতিহাসিক কারণে আমরা কয়েকটি প্ল্যাটফর্ম 2U < -1Lসত্য এবং অন্যকে মিথ্যা হিসাবে মূল্যায়ন করবে এই সত্য নিয়ে আটকে গেছি এবং আমরা এখন এই সত্যটির সাথে আটকেছি যে কিছু প্ল্যাটফর্ম স্বাক্ষরিত uint32_tএবং int32_tস্বাক্ষরিত হিসাবে একটি তুলনা কার্যকর করবে এবং কিছু স্বাক্ষরবিহীন হিসাবে, কিন্তু এর অর্থ এই নয় যে কমিটি সি-তে একটি wardর্ধ্ব-সামঞ্জস্যপূর্ণ উত্তরসূরির সংজ্ঞা দিতে পারে না যার মধ্যে এমন ধরণের অন্তর্ভুক্ত রয়েছে যার শব্দার্থকগুলি সমস্ত সংকলকগুলির সাথে সামঞ্জস্যপূর্ণ থাকবে।
সুপারক্যাট

1

একটি সাধারণ পার্থক্য:

প্রাক-প্রসেসিংয়ের সময় ধ্রুবকটিকে তার মান দিয়ে প্রতিস্থাপন করা হয়। সুতরাং আপনি একটি সংজ্ঞায়িত করার জন্য ডেরিফারেন্স অপারেটর প্রয়োগ করতে পারেন নি, তবে আপনি একটি ভেরিয়েবলের জন্য ডেরেফারেন্স অপারেটর প্রয়োগ করতে পারেন।

আপনি যেমন ধরুন, সংজ্ঞায়িত করা স্থায়ী কনস্টের দ্রুততর।

উদাহরণস্বরূপ, থাকা:

#define mymax 100

আপনি করতে পারবেন না printf("address of constant is %p",&mymax);

কিন্তু হচ্ছে

const int mymax_var=100

আপনি করতে পারেন printf("address of constant is %p",&mymax_var);

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

তবে, স্ট্যাটিক কনস্টের জন্য আমাদের একটি ভেরিয়েবল রয়েছে যা কোথাও বরাদ্দ করা হয়েছে। জিসিসির জন্য, স্ট্যাটিক কনস্টামটি প্রোগ্রামের পাঠ্য বিভাগে বরাদ্দ করা হয়।

উপরে, আমি রেফারেন্স অপারেটর সম্পর্কে বলতে চাই তাই রেফারেন্স সহ dereferences প্রতিস্থাপন।


1
আপনার উত্তরটি খুব ভুল। এটি সি সম্পর্কে, আপনার উত্তরটি সি ++ এর সাথে সম্পর্কিত, যা constকোয়ালিফায়ারের জন্য খুব আলাদা শব্দার্থকতা রয়েছে । সি -তে এনাম-কনস্ট্যান্ট ছাড়া অন্য কোনও প্রতীকিকা ধ্রুবক নেই । ক const intএকটি পরিবর্তনশীল। আপনি ভাষা এবং নির্দিষ্ট প্রয়োগগুলি গুলিয়ে ফেলেন। বস্তুটি কোথায় রাখার কোনও প্রয়োজন নেই। এবং এটি জিসিসির ক্ষেত্রেও সত্য নয়: সাধারণত এটি বিভাগে constযোগ্য ভেরিয়েবল রাখে .rodata। তবে এটি নির্ভর করে লক্ষ্য প্ল্যাটফর্মের উপর। এবং আপনি বোঝাচ্ছেন অ্যাড্রেস অফ অপারেটর &
এই সাইটের পক্ষে খুব সৎ

0

আমরা এমবিএফ 16 এক্স-তে উত্পাদিত এসেম্বলারের কোডটির দিকে চেয়েছিলাম ... উভয় রূপগুলি পাটিগণিত ক্রিয়াকলাপের জন্য একই কোডের ফলাফল দেয় (উদাহরণস্বরূপ এডিডি তাত্ক্ষণিক)।

তাই পুরানো স্টাইলের const intসময় টাইপ চেকের জন্য পছন্দ করা হয় #define। সম্ভবত এটি সংকলক-নির্দিষ্ট is সুতরাং আপনার উত্পাদিত এসেম্বলারের কোডটি পরীক্ষা করুন।


-1

আমি ঠিক আছি কিনা তা নিশ্চিত নই তবে আমার মতামতটিতে in #define d মান কল করা অন্য যে কোনও সাধারণভাবে ঘোষিত ভেরিয়েবল (বা কনস্ট মান) কল করার চেয়ে অনেক দ্রুত। এটি কারণ যখন প্রোগ্রাম চলমান থাকে এবং কিছু সাধারণভাবে ঘোষিত ভেরিয়েবল ব্যবহার করা দরকার তখন সেই পরিবর্তনশীলটি পেতে মেমরির যথাযথ স্থানে যেতে হবে।

বিপরীতে যখন এটি #defineডি মান ব্যবহার করে , প্রোগ্রামটিকে কোনও বরাদ্দকৃত মেমোরিতে ঝাঁপ দেওয়ার প্রয়োজন হয় না, এটি কেবল মান নেয়। যদি #define myValue 7এবং প্রোগ্রামটি কল করে myValue, এটি ঠিক যখন ডেকেছে ঠিক একইরকম আচরণ করে 7

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