প্রিলপ্রসেসর ম্যাক্রো বনাম ইনলাইন ফাংশন


115

একটি ইনলাইন ফাংশন কীভাবে প্রিপ্রোসেসর ম্যাক্রোর থেকে আলাদা হয়?


স্ট্যাকওভারফ্লো / উত্তরগুলি / 132738/… এর উত্তরগুলিতে আপনার প্রশ্নের সাথে সম্পর্কিত কিছু তথ্য রয়েছে।
লুক টুরাইল

উত্তর:


127

প্রিপ্রসেসর ম্যাক্রোগুলি কেবলমাত্র আপনার কোডে প্রয়োগ করা প্রতিস্থাপনের নিদর্শন। এগুলি আপনার কোডের প্রায় যে কোনও জায়গায় ব্যবহার করা যেতে পারে কারণ কোনও সংকলন শুরুর আগে সেগুলি তাদের বিস্তৃত জায়গায় প্রতিস্থাপন করা হয়েছিল।

ইনলাইন ফাংশনগুলি হ'ল আসল ফাংশন যার শরীর সরাসরি তাদের কল সাইটে intoুকিয়ে দেয়। সেগুলি কেবল সেখানে ব্যবহার করা যেতে পারে যেখানে কোনও ফাংশন কল উপযুক্ত।

এখন, ম্যাক্রো বনাম ইন-ইনলাইন ফাংশন যেমন কোনও ফাংশন-জাতীয় প্রসঙ্গে ব্যবহার করার পরামর্শ দেওয়া হচ্ছে:

  • ম্যাক্রোগুলি নিরাপদে টাইপ করেন না, এবং সিন্ট্যাটিকভাবে সঠিক কিনা তা নির্বিশেষে প্রসারিত করা যেতে পারে - সংকলন পর্বটি ম্যাক্রো প্রসারণ সমস্যার ফলে ত্রুটিগুলি রিপোর্ট করবে।
  • আপনি প্রত্যাশা করেন না এমন প্রেক্ষাপটে ম্যাক্রোগুলি ব্যবহার করা যেতে পারে, ফলস্বরূপ সমস্যা
  • ম্যাক্রোগুলি আরও নমনীয়, যাতে তারা অন্যান্য ম্যাক্রোগুলি প্রসারিত করতে পারে - যেখানে ইনলাইন ফাংশনগুলি অগত্যা এটি করে না।
  • ম্যাক্রোগুলি তাদের প্রসারণের কারণে পার্শ্ব প্রতিক্রিয়া দেখা দিতে পারে, যেহেতু ইনপুট এক্সপ্রেশনগুলি যেখানে প্যাটার্নে প্রদর্শিত হবে সেখানে অনুলিপি করা হয়।
  • ইনলাইন ফাংশনটি সর্বদা ইনলাইন হওয়ার গ্যারান্টিযুক্ত হয় না - কিছু সংকলক কেবল রিলিজ বিল্ডগুলিতে এটি করেন বা যখন তারা বিশেষভাবে এটির জন্য কনফিগার করা থাকে তখন। এছাড়াও, কিছু ক্ষেত্রে ইনলাইন করা সম্ভব নাও হতে পারে।
  • ইনলাইন ফাংশনগুলি ভেরিয়েবলের (বিশেষত স্থিতিশীল) জন্য সুযোগ প্রদান করতে পারে, প্রিপ্রোসেসর ম্যাক্রো কেবল কোড ব্লক {...} এ করতে পারে এবং স্থির ভেরিয়েবলগুলি ঠিক একইভাবে আচরণ করবে না।

39
ইনলাইন ফাংশনটি সর্বদা ইনলাইন্ড হওয়ার গ্যারান্টিযুক্ত হয় না: কারণ এটি করার ফলে সংকলক ইনলাইন করবে না ধীর কোড তৈরি করবে ইত্যাদি etc. সংকলকটি অনেক বিশ্লেষণ করে যা ইঞ্জিনিয়ার পারবেন না এবং সঠিক কাজটি করে।
মার্টিন ইয়র্ক

14
আমি বিশ্বাস করি যে রিকার্সিভ ফাংশনগুলি এমন একটি উদাহরণ যেখানে বেশিরভাগ সংকলক ইনলাইনিং উপেক্ষা করে।
এল বুশকিন

এই ক্ষেত্রে সি ++ এর তুলনায় সি-তে কোনও গুরুত্বপূর্ণ পার্থক্য রয়েছে কি?
rzetterberg

7
একটি বিষয় উল্লেখ নেই যা হ'ল ইনলাইনিং সংকলন পতাকা দ্বারা প্রভাবিত হতে পারে। উদাহরণস্বরূপ, আপনি যখন সর্বোচ্চ গতির জন্য তৈরি করেন (যেমন জিসিসি-ও ২ / -ओ 3) সংকলকটি অনেকগুলি ফাংশনটি ইনলাইন করতে বেছে নেবে, তবে আপনি যখন ন্যূনতম আকারের (-Os) তৈরি করেন তবে সাধারণত একবারে কেবল (বা খুব ছোট ফাংশন) ডাকা হবে )। ম্যাক্রোগুলির সাথে এ জাতীয় পছন্দ নেই।
dbrank0

ম্যানক্রো অ্যাক্সেস স্পেসিফায়ার (যেমন, ব্যক্তিগত বা সুরক্ষিত) দিয়ে কভার করতে পারে না যখন ইনলাইন কার্যগুলি সম্ভব হয়।
হিট এর

78

প্রথমত, প্রিপ্রসেসর ম্যাক্রোগুলি সংকলনের আগে কোডে কেবল "কপি পেস্ট" হয় are সুতরাং কোনও ধরণের চেকিং নেই , এবং কিছু পার্শ্ব প্রতিক্রিয়া উপস্থিত হতে পারে

উদাহরণস্বরূপ, আপনি যদি 2 টি মান তুলনা করতে চান:

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

পার্শ্ব প্রতিক্রিয়াগুলি প্রদর্শিত হয় যদি আপনি max(a++,b++)উদাহরণস্বরূপ ব্যবহার করেন ( aবা bদুবার বাড়ানো হবে)। পরিবর্তে, ব্যবহার করুন (উদাহরণস্বরূপ)

inline int max( int a, int b) { return ((a<b)?b:a); }

3
কেবল আপনার উদাহরণটিতে যোগ করতে চাই যে পার্শ্ব প্রতিক্রিয়া ছাড়াও ম্যাক্রো অতিরিক্ত কাজের max(fibonacci(100), factorial(10000))
চাপও

টাইপ চেকিংয়ের বিষয়ে প্রত্যেকে কথা বলে তবে কেবল আপনি একটি বাস্তব-জগতের উদাহরণ দিয়েছিলেন, এজন্যই আমি এই উত্তরটিকে upvote করেছি।
ইভানজিনহো

16

ইনলাইন ফাংশনটি সংকলক দ্বারা প্রসারিত করা হয়েছে যেখানে ম্যাক্রো প্রিপ্রসেসর দ্বারা প্রসারিত করা হয়েছে যা কেবল পাঠ্য প্রতিস্থাপন।

  • ফাংশন কল চলাকালীন টাইপ চেকিং করা হয় যখন ম্যাক্রো অনুরোধ সময় কোন ধরণের চেকিং হয়।

  • যুক্তি পুনরায় মূল্যায়ন এবং ক্রিয়াকলাপের ক্রমের কারণে ম্যাক্রো বিস্তারের সময় অযাচিত ফলাফল এবং অদক্ষতা দেখা দিতে পারে। উদাহরণ স্বরূপ

    #define MAX(a,b) ((a)>(b) ? (a) : (b))
    int i = 5, j = MAX(i++, 0);

    ফলাফল হবে

    int i = 5, j = ((i++)>(0) ? (i++) : (0));
  • ম্যাক্রো যুক্তিগুলি ম্যাক্রো প্রসারণের আগে মূল্যায়ন করা হয় না

    #define MUL(a, b) a*b
    int main()
    {
      // The macro is expended as 2 + 3 * 3 + 5, not as 5*8
      printf("%d", MUL(2+3, 3+5));
     return 0;
    }
    // Output: 16`
  • ফাংশনের ক্ষেত্রে মানগুলি ফেরত দিতে রিটার্ন কীওয়ার্ডটি ম্যাক্রোগুলিতে ব্যবহার করা যায় না।

  • ইনলাইন ফাংশনগুলি ওভারলোড করা যায়

  • টোকেন-পেস্টিং অপারেটর নামে ## অপারেটর ব্যবহার করে ম্যাক্রোগুলিতে পাস হওয়া টোকেনগুলি সংহত করা যেতে পারে।

  • ম্যাক্রোগুলি সাধারণত কোড পুনরায় ব্যবহারের জন্য ব্যবহৃত হয় যেখানে ইনলাইন ফাংশন হিসাবে ফাংশন কল চলাকালীন সময় ওভারহেড (অতিরিক্ত সময়) নির্মূল করতে ব্যবহৃত হয় (সাব্রোটিনে ঝাঁপ এড়ানো)।


13

মূল পার্থক্য হ'ল টাইপ চেকিং। সংকলকটি ইনপুট মান হিসাবে যা পাস করবে তা ফাংশনে প্রেরণ করা যায় কি না তা পরীক্ষা করে। এটি প্রিপ্রোসেসর ম্যাক্রোগুলির সাথে সত্য নয় - এগুলি কোনও প্রকারের চেকিংয়ের আগে প্রসারিত হয় এবং এর ফলে ত্রুটিগুলি সনাক্ত করা গুরুতর এবং শক্ত হতে পারে।

এখানে আরও কয়েকটি কম সুস্পষ্ট পয়েন্ট বর্ণিত হয়েছে।


11

ইতিমধ্যে প্রদত্তদের মধ্যে আরও একটি পার্থক্য যুক্ত করতে: আপনি #defineডিবাগারে কোনও পদক্ষেপ নিতে পারবেন না , তবে আপনি একটি ইনলাইন ফাংশনটি দিয়ে যেতে পারেন।



3

ইনলাইন ফাংশনগুলি ম্যাক্রোগুলির সমান (কারণ ফাংশন কোডটি সংকলনের সময় কলের বিন্দুতে প্রসারিত হয়), ইনলাইন ফাংশনগুলি সংকলক দ্বারা পার্স করা হয়, যেখানে ম্যাক্রো প্রিপ্রসেসর দ্বারা প্রসারিত হয়। ফলস্বরূপ, বেশ কয়েকটি গুরুত্বপূর্ণ পার্থক্য রয়েছে:

  • ইনলাইন ফাংশনগুলি সাধারণ ফাংশনগুলিতে প্রয়োগ করা সমস্ত ধরণের সুরক্ষা প্রোটোকল অনুসরণ করে।
  • ইনলাইন ফাংশনগুলি ফাংশন ঘোষণায় ইনলাইন মূলশব্দ অন্তর্ভুক্ত ব্যতীত অন্য কোনও ফাংশনের মতো একই সিনট্যাক্স ব্যবহার করে নির্দিষ্ট করা হয়।
  • ইনলাইন ফাংশনে আর্গুমেন্ট হিসাবে পাস করা এক্সপ্রেশনগুলি একবার মূল্যায়ন করা হয়।
  • কিছু ক্ষেত্রে ম্যাক্রোগুলির পক্ষে যুক্তি হিসাবে প্রকাশিত অভিব্যক্তিগুলি একাধিকবার মূল্যায়ন করা যেতে পারে। http://msdn.microsoft.com/en-us/library/bf6bf4cf.aspx

  • প্রাক-সংকলনের সময় ম্যাক্রোগুলি প্রসারিত হয়, আপনি সেগুলি ডিবাগিংয়ের জন্য ব্যবহার করতে পারবেন না, তবে আপনি ইনলাইন ফাংশন ব্যবহার করতে পারেন।

- ভাল নিবন্ধ : http://www.codeguru.com/forum/showpost.php?p=1093923&postcount=1

;


2

একটি ইনলাইন ফাংশন মান শব্দার্থবিজ্ঞান বজায় রাখে, তবে একটি প্রিপ্রসেসর ম্যাক্রো কেবল সিনট্যাক্সটি অনুলিপি করে। আপনি একাধিকবার আর্গুমেন্ট ব্যবহার করলে আপনি প্রিপ্রোসেসর ম্যাক্রো সহ খুব সূক্ষ্ম বাগ পেতে পারেন - উদাহরণস্বরূপ যদি যুক্তিতে "i ++" এর মত মিউটেশন থাকে যা দুবার মৃত্যুদণ্ড কার্যকর করা বেশ অবাক করে। একটি ইনলাইন ফাংশনটিতে এই সমস্যা থাকবে না।


1

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


1

ম্যাক্রো এবং ইনলাইন ফাংশনের মধ্যে পার্থক্য জানতে , প্রথমে আমাদের জানা উচিত যে তারা ঠিক কী এবং কখন তাদের ব্যবহার করা উচিত।

ফাংশন :

int Square(int x){
return(x*X);
}
int main()
{
int value = 5;
int result = Square(value);
cout << result << endl;
}
  • ফাংশন কলগুলির সাথে ওভারহেড যুক্ত রয়েছে, ফাংশন কার্যকর হওয়ার পরে এটি কোথায় ফিরে আসতে হবে তা জানতে হবে এবং স্ট্যাক মেমোরিতে মানটি সংরক্ষণ করতে হবে।

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

ম্যাক্রো:

# define Square(x) x*x;
int main()
{
int value = 5;
int result = Square(value);
cout << result << endl;
}
  • ম্যাক্রোস প্রিপ্রোসেসিং পর্যায়ে কাজ করে অর্থাৎ এই পর্যায়ে # কীওয়ার্ডের সাথে লিখিত বিবৃতিগুলি সামগ্রী হিসাবে প্রতিস্থাপন করা হবে ie

int ফলাফল = বর্গ (x * x)

তবে ম্যাক্রোগুলির সাথে এর সাথে সম্পর্কিত বাগ রয়েছে।

#define Square(x) x*x
int main() {
    int val = 5;
    int result = Square(val + 1);
    cout << result << endl;
    return 0;
}

এখানে আউটপুট 11 নয় 36

অনলাইন কাজ :

inline int Square(int x) {
    return x * x;
}

int main() {
    using namespace std;
    int val = 5;
    int result = Square(val + 1);
    cout << result << endl;
    return 0;
}

আউটপুট 36

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

ম্যাক্রো এবং ইনলাইন ফাংশনগুলির মধ্যে তুলনা:

  1. ম্যাক্রোস প্রতিস্থাপনের মাধ্যমে কাজ করে, যেখানে ইনলাইন ফাংশনগুলিতে, ফাংশন কলটি শরীরের সাথে প্রতিস্থাপন করা হয়।
  2. প্রতিস্থাপনের কারণে ম্যাক্রোগুলি ত্রুটিযুক্ত, যখন ইনলাইন ফাংশনগুলি ব্যবহার করা নিরাপদ।
  3. ম্যাক্রোগুলির ঠিকানা নেই যেখানে ইনলাইন ফাংশনগুলির ঠিকানা রয়েছে।
  4. কোডের একাধিক লাইন সহ ম্যাক্রোগুলি ব্যবহার করা কঠিন, যখন ইনলাইন ফাংশনগুলি নেই।
  5. সি ++ এ ম্যাক্রোগুলি সদস্য ফাংশনগুলির সাথে ব্যবহার করা যাবে না যেখানে ইনলাইন ফাংশন হতে পারে।

উপসংহার:

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

  • বড় ফাংশন
  • অনেকগুলি শর্তাধীন তর্ক রয়েছে functions
  • লুপগুলি সহ পুনরাবৃত্তির কোড এবং কোড etc.

যা একটি ভাল জিনিস, কারণ এটি যখনই সংকলক মনে করে যে জিনিসগুলি অন্যভাবে করা ভাল।


ঠিক যেমন একটি মন্তব্য: ম্যাক্রো বন্ধনী সহ একই সংখ্যাতে মূল্যায়ন করার জন্য স্থির করা যেতে পারে। যাইহোক, এটি এখনও ত্রুটিযুক্ত প্রবণ, যেহেতু আপনাকে বাস্তবের সময় নিখুঁত বোবা সাবস্ক্রিপশন এবং সমস্ত ক্ষেত্রে সম্পর্কে চিন্তা করা দরকার।
মাইক

0

জিসিসিতে (আমি অন্যের বিষয়ে নিশ্চিত নই), কোনও ফাংশনটিকে ইনলাইনে ঘোষণা করা সংকলকটির জন্য কেবল একটি ইঙ্গিত। এটি যখনই ডাকা হয় তখন এটি ফাংশনের মূল অংশটি অন্তর্ভুক্ত করে কিনা তা নির্ধারণের জন্য দিন শেষে সংকলকটি এখনও নির্ভর করে।

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

#define MACRO_FUNC(X) ...

যেখানে MACRO_FUNC স্পষ্টতই ফাংশনটির মূল সংজ্ঞা দেয়। বিশেষ যত্ন নেওয়া দরকার তাই এটি সঠিকভাবে চলতে পারে সমস্ত ক্ষেত্রেই একটি ফাংশন ব্যবহার করা যেতে পারে, উদাহরণস্বরূপ একটি দুর্বল লিখিত MACRO_FUNC এতে ত্রুটির কারণ হতে পারে

if(MACRO_FUNC(y)) {
 ...body
}

কোনও সমস্যা নেই সেখানে একটি সাধারণ ফাংশন ব্যবহার করা যেতে পারে।


0

কোডিংয়ের দৃষ্টিকোণ থেকে, একটি ইনলাইন ফাংশন একটি ফাংশনের মতো। সুতরাং, একটি ইনলাইন ফাংশন এবং ম্যাক্রোর মধ্যে পার্থক্যগুলি কোনও ফাংশন এবং ম্যাক্রোর মধ্যে পার্থক্যগুলির সমান।

সংকলনের দৃষ্টিকোণ থেকে, একটি ইনলাইন ফাংশন ম্যাক্রোর অনুরূপ। এটি সরাসরি কোডে ইনজেকশন দেওয়া হয়, বলা হয় না।

সাধারণভাবে, আপনাকে কিছুটা অপেক্ষাকৃত অপ্টিমাইজেশান মিশ্রিত করার সাথে ইনলাইন ফাংশনগুলিকে নিয়মিত ফাংশন হিসাবে বিবেচনা করা উচিত And প্রায়শই সংকলক বিভিন্ন কারণে কোনও ক্রিয়াকলাপটি ইনলাইন করার জন্য প্রোগ্রামার কর্তৃক যে প্রচেষ্টা চালিয়ে যায় তা আনন্দের সাথে উপেক্ষা করবে।


0

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


-1
#include<iostream>
using namespace std;
#define NUMBER 10 //macros are preprocessed while functions are not.
int number()
{ 
    return 10;
}
/*In macros, no type checking(incompatible operand, etc.) is done and thus use of micros can lead to errors/side-effects in some cases. 
However, this is not the case with functions.
Also, macros do not check for compilation error (if any). Consider:- */
#define CUBE(b) b*b*b
int cube(int a)
{
 return a*a*a;
}
int main()
{
 cout<<NUMBER<<endl<<number()<<endl;
 cout<<CUBE(1+3); //Unexpected output 10
 cout<<endl<<cube(1+3);// As expected 64
 return 0;
}

ম্যাক্রোগুলি ফাংশনগুলির তুলনায় সাধারণত দ্রুত হয় কারণ এগুলি প্রকৃত ফাংশন কল ওভারহেডের সাথে জড়িত না।

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

ম্যাক্রো সাধারণত একটি লাইনার হয়। তবে এগুলি একাধিক লাইনের সমন্বয়ে থাকতে পারে functions কার্যক্রমে এ জাতীয় কোনও বাধা নেই।


#define TWO_N(n) 2 << nতারপরে আর কত মজা পাবেন cout << CUBE(TWO_N(3 + 1)) << endl;? (আউটপুটটির লাইনগুলি endlশুরু করার চেয়ে শেষ করা ভাল ))
জোনাথন লেফলার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.