প্রিপ্রসেসর ম্যাক্রোস মন্দ কেন এবং এর বিকল্পগুলি কী?


94

আমি সর্বদা এটি জিজ্ঞাসা করেছি তবে সত্যিকারের উত্তম উত্তর আমি কখনও পাইনি; আমি মনে করি যে প্রথম "হ্যালো ওয়ার্ল্ড" লেখার আগে প্রায় কোনও প্রোগ্রামার "ম্যাক্রো কখনই ব্যবহার করা উচিত নয়", "ম্যাক্রো অশুভ" এবং এই জাতীয় বাক্যাংশের মুখোমুখি হয়েছিল, আমার প্রশ্ন: কেন? নতুন সি ++ এর সাথে এত বছর পরেও কি আসল বিকল্প আছে?

সহজ অংশটি ম্যাক্রোগুলির মতো #pragma, যা প্ল্যাটফর্ম নির্দিষ্ট এবং সংকলক নির্দিষ্ট, এবং বেশিরভাগ সময় তাদের মতো গুরুতর ত্রুটি #pragma onceথাকে কমপক্ষে 2 টি গুরুত্বপূর্ণ পরিস্থিতিতে ত্রুটি প্রবণ হয়: বিভিন্ন পথে একই নাম এবং কয়েকটি নেটওয়ার্ক সেটআপ এবং ফাইল সিস্টেম রয়েছে।

তবে সাধারণভাবে, ম্যাক্রো এবং তাদের ব্যবহারের বিকল্পগুলি সম্পর্কে কী?


19
#pragmaম্যাক্রো নয়।
এফওএফ

4
@ ফুফ প্রিপ্রোসেসর নির্দেশ?
ব্যবহারকারী 1849534

6
@ ইউজার 1849534: হ্যাঁ, এটাই ... এবং ম্যাক্রো সম্পর্কিত পরামর্শটি কথা বলছে না #pragma
বেন ভয়েগট

4
আপনি এর সাথে constexpr, inlineফাংশনগুলি এবং templates, এবং অনেক কিছু করতে পারেন তবে boost.preprocessorএবং chaosম্যাক্রোদের তাদের স্থান রয়েছে তা দেখাতে পারেন। পার্থক্য সংকলক, প্ল্যাটফর্ম ইত্যাদির জন্য কনফিগারেশন ম্যাক্রোগুলির উল্লেখ না করা
ব্র্যান্ডন

উত্তর:


165

ম্যাক্রোগুলি অন্য যে কোনও সরঞ্জামের মতো - হত্যায় ব্যবহৃত একটি হাতুড়িটি মন্দ নয় কারণ এটি একটি হাতুড়ি। ব্যক্তি যেভাবে এটি ব্যবহার করে এটি মন্দ। আপনি যদি নখে হাতুড়ি রাখতে চান তবে একটি হাতুড়ি একটি নিখুঁত সরঞ্জাম।

ম্যাক্রোগুলির কয়েকটি দিক রয়েছে যা সেগুলি "খারাপ" করে তোলে (আমি পরের দিকে প্রসারিত করব এবং বিকল্পগুলির পরামর্শ দেব):

  1. আপনি ম্যাক্রো ডিবাগ করতে পারবেন না।
  2. ম্যাক্রো প্রসারণ অদ্ভুত পার্শ্ব প্রতিক্রিয়া হতে পারে।
  3. ম্যাক্রোগুলির কোনও "নেমস্পেস" নেই, সুতরাং আপনার যদি এমন ম্যাক্রো থাকে যা অন্য কোথাও ব্যবহৃত নামের সাথে সংঘর্ষ হয় তবে আপনি ম্যাক্রো প্রতিস্থাপন পাবেন যেখানে আপনি এটি চান নি এবং এটি সাধারণত অদ্ভুত ত্রুটি বার্তাগুলির দিকে পরিচালিত করে।
  4. ম্যাক্রোসগুলি এমন জিনিসগুলিকে প্রভাবিত করতে পারে যা আপনি বুঝতে পারেন না।

সুতরাং আসুন এখানে কিছুটা প্রসারিত করুন:

1) ম্যাক্রোগুলি ডিবাগ করা যায় না। যখন আপনার কাছে কোনও ম্যাক্রো রয়েছে যা কোনও সংখ্যা বা একটি স্ট্রিংয়ে অনুবাদ করে, উত্স কোডটিতে ম্যাক্রোর নাম এবং অনেক ডিবাগার থাকবে, আপনি ম্যাক্রোর সাথে অনুবাদ করে "দেখতে" পারবেন না। সুতরাং আপনি আসলে জানেন না যে কি চলছে।

প্রতিস্থাপন : ব্যবহার enumবাconst T

"ফাংশন-সদৃশ" ম্যাক্রোগুলির জন্য, কারণ ডিবাগারটি "যেখানে আপনি যেখানে থাকেন" সোর্স লাইনের উপর "কাজ করে, আপনার ম্যাক্রো একক বিবৃতি হিসাবে কাজ করবে, এটি কোনও বিবৃতি বা একশ হোক না কেন। কী চলছে তা নির্ধারণ করা শক্ত করে তোলে।

প্রতিস্থাপন : ফাংশনগুলি ব্যবহার করুন - "দ্রুত" হওয়া দরকার হলে ইনলাইন করুন (তবে সাবধান থাকবেন যে খুব বেশি ইনলাইন কোনও ভাল জিনিস নয়)

2) ম্যাক্রো বিস্তৃতি অদ্ভুত পার্শ্ব প্রতিক্রিয়া হতে পারে।

বিখ্যাত এক #define SQUARE(x) ((x) * (x))এবং ব্যবহার x2 = SQUARE(x++)। এটি বাড়ে x2 = (x++) * (x++);, যা, যদিও এটি বৈধ কোড ছিল [1], প্রায় অবশ্যই প্রোগ্রামার যা চেয়েছিল তা নয়। যদি এটি কোনও ফাংশন হয় তবে এক্স ++ করা ভাল হবে এবং এক্স কেবল একবার বৃদ্ধি করবে।

আর একটি উদাহরণ ম্যাক্রোগুলিতে "যদি অন্যথায়" হয় তবে বলুন আমাদের এটি আছে:

#define safe_divide(res, x, y)   if (y != 0) res = x/y;

এবং তারপর

if (something) safe_divide(b, a, x);
else printf("Something is not set...");

এটি আসলে সম্পূর্ণ ভুল জিনিস হয়ে যায় ...

প্রতিস্থাপন : বাস্তব ফাংশন।

3) ম্যাক্রোর কোনও নামস্থান নেই

আমাদের যদি ম্যাক্রো থাকে:

#define begin() x = 0

এবং আমাদের সি ++ তে কিছু কোড রয়েছে যা ব্যবহার শুরু করে:

std::vector<int> v;

... stuff is loaded into v ... 

for (std::vector<int>::iterator it = myvector.begin() ; it != myvector.end(); ++it)
   std::cout << ' ' << *it;

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

প্রতিস্থাপন : ঠিক আছে, "বিধি" হিসাবে প্রতিস্থাপনের মতো এতটা নেই - কেবল ম্যাক্রোগুলির জন্য বড় হাতের নাম ব্যবহার করুন এবং অন্যান্য জিনিসের জন্য সমস্ত বড় হাতের নাম কখনও ব্যবহার করবেন না।

4) ম্যাক্রোসের এমন প্রভাব রয়েছে যা আপনি বুঝতে পারবেন না

এই ফাংশনটি নিন:

#define begin() x = 0
#define end() x = 17
... a few thousand lines of stuff here ... 
void dostuff()
{
    int x = 7;

    begin();

    ... more code using x ... 

    printf("x=%d\n", x);

    end();

}

এখন, ম্যাক্রোর দিকে না তাকিয়ে আপনি ভাববেন যে সূচনাটি একটি ফাংশন, এটি এক্সকে প্রভাবিত করবে না।

এই ধরণের জিনিস, এবং আমি আরও জটিল উদাহরণগুলি দেখেছি, সত্যিই আপনার দিনকে জগাখিচুড়ি করতে পারে!

প্রতিস্থাপন : হয় এক্স সেট করতে ম্যাক্রো ব্যবহার করবেন না, বা একটি আর্গুমেন্ট হিসাবে এক্স পাস করুন।

এমন সময় আছে যখন ম্যাক্রোগুলি ব্যবহার করা অবশ্যই উপকারী। একটি উদাহরণ ফাইল / লাইন তথ্য পাস করার জন্য ম্যাক্রোগুলির সাথে একটি ফাংশন মোড়ানো:

#define malloc(x) my_debug_malloc(x, __FILE__, __LINE__)
#define free(x)  my_debug_free(x, __FILE__, __LINE__)

এখন আমরা my_debug_mallocকোডটিতে নিয়মিত ম্যালোক হিসাবে ব্যবহার করতে পারি , তবে এটিতে অতিরিক্ত যুক্তি রয়েছে, সুতরাং যখন এটি শেষ হয় এবং আমরা "কোন স্মৃতি উপাদানগুলি মুক্তি পায় নি" স্ক্যান করি, তখন আমরা মুদ্রণ করতে পারি যেখানে বরাদ্দটি এতদূর হয়েছে প্রোগ্রামার লিকটি সনাক্ত করতে পারে।

[1] "এক সিকোয়েন্স পয়েন্টে" একবারে একাধিক পরিবর্তনশীল আপডেট করা এটি অপরিজ্ঞাত আচরণ। একটি ক্রম বিন্দু বিবৃতি হিসাবে ঠিক একই নয়, তবে বেশিরভাগ উদ্দেশ্য এবং উদ্দেশ্যগুলির জন্য আমাদের এটিকে বিবেচনা করা উচিত। এটি করার x++ * x++ফলে xদু'বার আপডেট হবে যা অপরিজ্ঞাত এবং সম্ভবত বিভিন্ন সিস্টেমে বিভিন্ন মান এবং বিভিন্ন ফলাফলের মান হতে xপারে।


6
if elseসমস্যার ম্যাক্রো শরীরে মোড়কে সমাধান করা যেতে পারে do { ... } while(0)। এক হিসাবে এই আচরণ করবে সম্মান সঙ্গে আশা ifএবং forএবং অন্যান্য সম্ভাব্য-ঝুঁকিপূর্ণ কন্ট্রোল- প্রবাহ সমস্যা। তবে হ্যাঁ, একটি আসল ফাংশন সাধারণত একটি ভাল সমাধান। #define macro(arg1) do { int x = func(arg1); func2(x0); } while(0)
অ্যারন ম্যাকডেইড

11
@ অ্যারোনম্যাকডেইড: হ্যাঁ, এমন কিছু কর্মক্ষেত্র রয়েছে যা এই ম্যাক্রোগুলিতে প্রকাশিত কিছু সমস্যা সমাধান করে। আমার পোস্টের পুরো বিষয়টিটি ম্যাক্রোগগুলি কীভাবে ভালভাবে করা যায় তা দেখানো ছিল না, "ম্যাক্রোগুলি ভুল হওয়া কত সহজ", সেখানে একটি ভাল বিকল্প রয়েছে। এই বলেছিল যে, এমন কিছু জিনিস রয়েছে যা ম্যাক্রোগুলি খুব সহজে সমাধান করে এবং এমন সময় আসে যখন ম্যাক্রোগুলিও সঠিকভাবে কাজ করে।
ম্যাটস পিটারসন

4
3 পয়েন্টে ত্রুটিগুলি আসলেই আর কোনও সমস্যা নয়। আধুনিক সংকলক যেমন ক্ল্যাংয়ের মতো কিছু বলবে note: expanded from macro 'begin'এবং কোথায় beginসংজ্ঞায়িত তা প্রদর্শন করবে ।
kirbyfan64sos

4
ম্যাক্রোগুলি অন্য ভাষায় অনুবাদ করা শক্ত।
মার্কো ভ্যান ডি ভুর্ট

4
@ ফ্রেঞ্চসোডোন্ডি: স্ট্যাকওভারফ্লো / প্রশ্নগুলি / ৪১636363৩৪/২ (এই উত্তরে কিছুটা নিচে, এটি আই ++ * আই ++ এবং এরকম সম্পর্কে কথা বলেছে
ম্যাট পিটারসন

21

"ম্যাক্রোস অশুভ" প্রবাদটি সাধারণত # ডেফাইন ব্যবহার করে বোঝায়, # প্রাগমা নয়।

বিশেষত, অভিব্যক্তি এই দুটি ক্ষেত্রে বোঝায়:

  • ম্যাক্রো হিসাবে যাদু সংখ্যা সংজ্ঞায়িত করা

  • এক্সপ্রেশনগুলি প্রতিস্থাপন করতে ম্যাক্রো ব্যবহার করা হচ্ছে

নতুন সি ++ 11 এর সাথে এত বছর পরেও কি আসল বিকল্প আছে?

হ্যাঁ, উপরের তালিকার আইটেমগুলির জন্য (ম্যাজিক সংখ্যাগুলি কনস্ট / কনস্টেক্সপ্রের সাথে সংজ্ঞায়িত করা উচিত এবং এক্সপ্রেশনগুলি [সাধারণ / ইনলাইন / টেম্পলেট / ইনলাইন টেম্পলেট] ফাংশন দিয়ে সংজ্ঞায়িত করা উচিত)।

ম্যাক্রো হিসাবে ম্যাজিক সংখ্যা সংজ্ঞায়িত করে এবং ম্যাক্রোগুলির সাহায্যে ম্যাক্রোগুলির মাধ্যমে পুনঃবিবেচনা অভিব্যক্তির মাধ্যমে (সেই সমস্ত অভিব্যক্তিগুলি মূল্যায়নের জন্য কার্যকারিতা সংজ্ঞায়নের পরিবর্তে) চালু করা কিছু সমস্যা রয়েছে:

  • যাদু সংখ্যার জন্য ম্যাক্রো সংজ্ঞায়িত করার সময়, সংকলক সংজ্ঞায়িত মানগুলির জন্য কোনও প্রকারের তথ্য ধরে রাখে না। এটি সংকলনের সতর্কতাগুলির (এবং ত্রুটিগুলি) সৃষ্টি করতে পারে এবং কোডটি ডিবাগ করে লোককে বিভ্রান্ত করতে পারে।

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

এই কোডটি বিবেচনা করুন:

#define max(a, b) ( ((a) > (b)) ? (a) : (b) )

int a = 5;
int b = 4;

int c = max(++a, b);

আপনি সি ও এসাইনমেন্টের পরে a এবং c এর 6 হবে আশা করবেন (যেমনটি হবে ম্যাক্রোর পরিবর্তে std :: সর্বোচ্চ ব্যবহারের মাধ্যমে)। পরিবর্তে, কোড সম্পাদন করে:

int c = ( ((++a) ? (b)) ? (++a) : (b) ); // after this, c = a = 7

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

এর অর্থ হ'ল আপনি যদি উপরে (ম্যাক্সের জন্য) উপরের ম্যাক্রোটি সংজ্ঞায়িত করেন তবে আপনি নীচের কোডগুলিতে আর সক্ষম হবেন #include <algorithm>না, যতক্ষণ না আপনি স্পষ্টভাবে লিখেছেন:

#ifdef max
#undef max
#endif
#include <algorithm>

ভেরিয়েবল / ফাংশনের পরিবর্তে ম্যাক্রো থাকার অর্থ আপনি তাদের ঠিকানা নিতে পারবেন না:

  • যদি কোনও ম্যাক্রো-এ-ধ্রুবক কোনও যাদু সংখ্যায় মূল্যায়ন করে তবে আপনি এটিকে ঠিকানার মাধ্যমে পাস করতে পারবেন না

  • ম্যাক্রো-এ-ফাংশনের জন্য, আপনি এটিকে শিকারী হিসাবে ব্যবহার করতে পারবেন না বা ফাংশনটির ঠিকানা নিতে পারবেন না বা এটি ফ্যান্টকার হিসাবে বিবেচনা করতে পারবেন না।

সম্পাদনা করুন: উদাহরণ হিসাবে, #define maxউপরের সঠিক বিকল্প :

template<typename T>
inline T max(const T& a, const T& b)
{
    return a > b ? a : b;
}

এটি একটি সীমাবদ্ধতার সাথে ম্যাক্রো যা কিছু করে তা করে: যদি আর্গুমেন্টগুলির ধরণগুলি আলাদা হয় তবে টেম্পলেট সংস্করণ আপনাকে সুস্পষ্ট হতে বাধ্য করে (যা আসলে নিরাপদ, আরও স্পষ্ট কোডের দিকে পরিচালিত করে):

int a = 0;
double b = 1.;
max(a, b);

যদি এই সর্বোচ্চটি ম্যাক্রো হিসাবে সংজ্ঞায়িত করা হয়, কোডটি সংকলন করবে (একটি সতর্কতা সহ)।

যদি এই সর্বোচ্চটি কোনও টেম্পলেট ফাংশন হিসাবে সংজ্ঞায়িত করা হয়, তবে সংকলকটি অস্পষ্টতাকে নির্দেশ করবে এবং আপনাকে বলতে হবে max<int>(a, b)বা হয় max<double>(a, b)(এবং এইভাবে স্পষ্টভাবে আপনার উদ্দেশ্যটি বর্ণনা করবে)।


4
এটি সি ++ 11 নির্দিষ্ট হতে হবে না; আপনি কেবল ম্যাক্রো-অ্যাস-এক্সপ্রেশন ব্যবহার এবং ম্যাক্রো-অ্যাস-কনস্ট্যান্টের ব্যবহার প্রতিস্থাপনের জন্য [স্থিতিশীল] কনস্ট / কনস্টেক্সপ্রের জন্য ফাংশন ব্যবহার করতে পারেন।
utnapistim

4
এমনকি সি 99 ব্যবহারের অনুমতি দেয় const int someconstant = 437;এবং এটি ম্যাক্রো ব্যবহারের প্রায় প্রতিটি উপায়েই ব্যবহার করা যেতে পারে। তেমনি ছোট ফাংশন জন্য। কয়েকটি জিনিস রয়েছে যেখানে আপনি ম্যাক্রো হিসাবে এমন কিছু লিখতে পারেন যা সিতে নিয়মিত প্রকাশে কাজ করে না (আপনি এমন কিছু তৈরি করতে পারেন যা কোনও ধরণের অ্যারে গড় গড় করে যা সি করতে পারে না - তবে সি ++ এর টেমপ্লেট রয়েছে যে জন্য). যদিও সি ++ 11 আরও কয়েকটি জিনিস যুক্ত করেছে যা "আপনার এর জন্য ম্যাক্রোর দরকার নেই", এটি বেশিরভাগ ইতিমধ্যে পূর্ববর্তী সি / সি ++ এ সমাধান হয়েছে।
ম্যাটস পিটারসন

একটি যুক্তি পাস করার সময় প্রাক-বর্ধন করা একটি ভয়ানক কোডিং অনুশীলন। এবং যে কেউ সি / সি ++ এ কোডিং করছে তাদের কোনও ফাংশন-মতো কল ম্যাক্রো নয় বলে মনে করা উচিত ।
স্টিফেনজি

অনেকগুলি প্রয়োগগুলি স্বেচ্ছায় শনাক্তকারীদের প্রথম বন্ধনীকরণ করে maxএবং minযদি সেগুলি বাম বন্ধনী অনুসরণ করে। তবে আপনার যেমন ম্যাক্রো সংজ্ঞায়িত করা উচিত নয় ...
এলএফ

14

একটি সাধারণ সমস্যা হ'ল:

#define DIV(a,b) a / b

printf("25 / (3+2) = %d", DIV(25,3+2));

এটি 5 নয়, 10 টি মুদ্রণ করবে কারণ প্রিপ্রসেসর এটি এভাবে প্রসারিত করবে:

printf("25 / (3+2) = %d", 25 / 3 + 2);

এই সংস্করণটি নিরাপদ:

#define DIV(a,b) (a) / (b)

4
আকর্ষণীয় উদাহরণ, মূলত তারা শব্দার্থবিজ্ঞান ছাড়াই কেবল টোকেন
ব্যবহারকারী 1849534

হ্যাঁ. তারা যেভাবে ম্যাক্রোকে দেওয়া হচ্ছে সেগুলি বাড়ানো হয়েছে। DIVম্যাক্রোর () প্রায় একজোড়া সঙ্গে পুনর্লিখিত করা যেতে পারে b
ফাজাজন

4
আপনার মানে #define DIV(a,b), না #define DIV (a,b), যা খুব আলাদা।
ধনী

6
#define DIV(a,b) (a) / (b)যথেষ্ট ভাল না; সাধারণ অনুশীলনের বিষয় হিসাবে, সর্বদা এই জাতীয় বাহ্যিক বন্ধনী যুক্ত করুন:#define DIV(a,b) ( (a) / (b) )
PJTraill

3

বিশেষত জেনেরিক কোড তৈরি করার জন্য ম্যাক্রোগুলি মূল্যবান (ম্যাক্রোর প্যারামিটারগুলি যে কোনও কিছু হতে পারে), কখনও কখনও পরামিতি সহ।

আরও, এই কোডটি ম্যাক্রোর বিন্দুতে স্থাপন করা (অর্থাত্ inোকানো) ব্যবহৃত হয়।

ওটিওএইচ, অনুরূপ ফলাফল এর সাথে পাওয়া যেতে পারে:

  • অতিরিক্ত লোড ফাংশন (বিভিন্ন পরামিতি ধরণের)

  • টেমপ্লেটগুলি, সি ++ এ (জেনেরিক প্যারামিটারের ধরণ এবং মান)

  • ইনলাইন ফাংশন (একক পয়েন্ট সংজ্ঞাতে লাফানোর পরিবর্তে, যেখানে তাদের বলা হয় সেখানে কোড কোড - তবে এটি সংকলকটির পরিবর্তে পুনঃসংশোধন)।

সম্পাদনা করুন: ম্যাক্রো কেন খারাপ:

1) আর্গুমেন্টগুলির কোনও টাইপ-চেকিং নেই (তাদের কোনও প্রকার নেই), তাই সহজেই অপব্যবহার করা যায় 2) কখনও কখনও খুব জটিল কোডে প্রসারিত হয়, যা প্রিপ্রোসেসড ফাইলটিতে সনাক্ত করা এবং বুঝতে অসুবিধা হতে পারে 3) ত্রুটি করা সহজ -ম্যাক্রোগুলিতে প্রোন কোড, যেমন:

#define MULTIPLY(a,b) a*b

এবং তারপর কল

MULTIPLY(2+3,4+5)

যে প্রসারিত

2 + 3 * 4 + 5 (এবং এতে নয়: (2 + 3) * (4 + 5%)।

দ্বিতীয়টির জন্য, আপনাকে সংজ্ঞায়িত করা উচিত:

#define MULTIPLY(a,b) ((a)*(b))

3

আমি মনে করি না যে আপনি প্রিপ্রোসেসর সংজ্ঞা বা ম্যাক্রোগুলি কল করার সাথে সাথে কোনও ত্রুটি আছে।

এগুলি সি / সি ++ এ পাওয়া একটি (মেটা) ভাষা ধারণা এবং অন্য যে কোনও সরঞ্জামের মতো তারা যদি আপনার জীবনযাপনকে আরও সহজ করে তুলতে পারে তবে আপনি কী করছেন তা আপনি জানেন। ম্যাক্রোগুলির সমস্যা হ'ল এগুলি আপনার সি / সি ++ কোডের আগে প্রক্রিয়া করা হয় এবং নতুন কোড উত্পন্ন করে যা ত্রুটিযুক্ত হতে পারে এবং সংকলক ত্রুটির কারণ হতে পারে যা সমস্ত স্পষ্ট obvious উজ্জ্বল দিকে তারা আপনাকে আপনার কোডটি পরিষ্কার রাখতে সাহায্য করতে পারে এবং সঠিকভাবে ব্যবহার করা হলে আপনাকে প্রচুর টাইপ করতে পারে, তাই এটি ব্যক্তিগত পছন্দ হিসাবে নেমে আসে।


এছাড়াও, অন্যান্য উত্তরের দ্বারা নির্দেশিত হিসাবে, খারাপভাবে ডিজাইন করা প্রিপ্রসেসর সংজ্ঞাগুলি বৈধ বাক্য গঠন সহ বিভিন্ন শব্দার্থক অর্থ সহ কোড তৈরি করতে পারে যার অর্থ কম্পাইলার অভিযোগ করবে না এবং আপনি আপনার কোডে একটি বাগ প্রবর্তন করেছেন যা খুঁজে পাওয়া আরও শক্ত হতে পারে।
সান্দি Hrvić

3

সি / সি ++ এ থাকা ম্যাক্রোগুলি সংস্করণ নিয়ন্ত্রণের জন্য একটি গুরুত্বপূর্ণ সরঞ্জাম হিসাবে পরিবেশন করতে পারে। একই কোডটি ম্যাক্রোগুলির একটি ছোটখাটো কনফিগারেশন সহ দুটি ক্লায়েন্টকে বিতরণ করা যেতে পারে। আমি মত জিনিস ব্যবহার

#define IBM_AS_CLIENT
#ifdef IBM_AS_CLIENT 
  #define SOME_VALUE1 X
  #define SOME_VALUE2 Y
#else
  #define SOME_VALUE1 P
  #define SOME_VALUE2 Q
#endif

এই জাতীয় কার্যকারিতা ম্যাক্রোগুলি ছাড়া এত সহজে সম্ভব নয়। ম্যাক্রোস আসলে একটি দুর্দান্ত সফ্টওয়্যার কনফিগারেশন ম্যানেজমেন্ট সরঞ্জাম এবং কোডের পুনরায় ব্যবহারের শর্টকাট তৈরির উপায় নয়। ম্যাক্রোগুলিতে পুনরায় ব্যবহারযোগ্যতার উদ্দেশ্যে কার্যকারিতা সংজ্ঞায়িত করে অবশ্যই সমস্যা তৈরি করতে পারে।


একটি কোডবেসের বাইরে দুটি ভেরিয়েন্ট তৈরি করতে সংকলনের সময় ম্যাক্রো মানগুলি সেমিডলাইনে সেট করা সত্যিই দুর্দান্ত। সংযম.
কেভিনফ

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

1

আমি মনে করি যে সমস্যাটি হ'ল ম্যাক্রোগুলি সংকলক দ্বারা ভালভাবে অনুকূলিত হয় নি এবং পড়তে এবং ডিবাগ করতে "কুশ্রী"।

প্রায়শই একটি ভাল বিকল্প হ'ল জেনেরিক ফাংশন এবং / অথবা ইনলাইন ফাংশন।


4
ম্যাক্রোগুলি ভাল-অনুকূলিত হয় না এমন বিশ্বাস করতে আপনাকে কীসের দিকে নিয়ে যায়? এগুলি সহজ পাঠ্য প্রতিস্থাপন এবং ফলাফলটি ম্যাক্রোগুলিবিহীন কোডের মতোই অনুকূলিত করা হয়েছে।
বেন ভয়েগট

@BenVoigt কিন্তু তারা শব্দার্থবিদ্যা বিবেচনা করা হয় না এবং এই কিছু যে হিসাবে "না অনুকূল" বিবেচনা করা যেতে পারে হতে পারে ... অন্তত এই যে বিষয়ে আমার প্রথম কয়েক সপ্তাহ হল stackoverflow.com/a/14041502/1849534
user1849534

4
@ ইউজার 1849534: সংকলনের প্রসঙ্গে "অপ্টিমাইজড" শব্দের অর্থ এটাই নয়।
বেন ভয়েগট

4
@ বেনভয়েগ্ট ঠিক বলেছেন, ম্যাক্রোগুলি কেবল পাঠ্য প্রতিস্থাপন। সংকলকটি কেবল কোডটির নকল করুন, এটি কোনও পারফরম্যান্স সমস্যা নয় তবে প্রোগ্রামের আকার বাড়াতে পারে। বিশেষত কিছু প্রসঙ্গে যেখানে আপনার প্রোগ্রামের আকারের সীমাবদ্ধতা রয়েছে সত্য true কিছু কোড ম্যাক্রোগুলির সাথে এতটাই পরিপূর্ণ যে প্রোগ্রামটির আকার দ্বিগুণ।
ডেভিড ইকার্দি

1

প্রিপ্রসেসর ম্যাক্রোগগুলি মন্দ হয় না যখন এগুলি উদ্দেশ্যে উদ্দেশ্যে ব্যবহার করা হয়:

  • #Ifdef ধরণের কনস্ট্রাক্টস ব্যবহার করে একই সফ্টওয়্যারটির বিভিন্ন রিলিজ তৈরি করা হয়, উদাহরণস্বরূপ বিভিন্ন অঞ্চলের উইন্ডোজ প্রকাশ।
  • কোড পরীক্ষার সম্পর্কিত মান নির্ধারণের জন্য।

Alternatives- ওয়ান স্টার, এক্সএমএল, একই উদ্দেশ্যে JSON ফর্ম্যাটে কনফিগারেশন ফাইল কিছু বাছাই ব্যবহার করতে পারেন। তবে তাদের ব্যবহারের কোডে রান টাইম এফেক্ট থাকবে যা একটি প্রিপ্রসেসর ম্যাক্রো এড়াতে পারে।


4
যেহেতু সি ++ ১ cons কনসেক্সটপ্রপ + যদি + কনফিট্সপ্রের ভেরিয়েবলগুলি অন্তর্ভুক্ত করে এমন একটি শিরোলেখ ফাইল যদি # ইফদেফগুলি প্রতিস্থাপন করতে পারে।
এনহেক্স
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.