স্ট্যান্ডার্ড সি প্রিপ্রেসেসর
$ cat xx.c
#define VARIABLE 3
#define PASTER(x,y) x ## _ ## y
#define EVALUATOR(x,y) PASTER(x,y)
#define NAME(fun) EVALUATOR(fun, VARIABLE)
extern void NAME(mine)(char *x);
$ gcc -E xx.c
# 1 "xx.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "xx.c"
extern void mine_3(char *x);
$
ইন্ডিরিশনের দুটি স্তর
অন্য উত্তরের মন্তব্যে ক্যাড রক্স জিজ্ঞাসা করলেন কেন এটি দুটি স্তরের ইন্ডিয়ারেশন প্রয়োজন। উল্টাপাল্টা উত্তর হ'ল স্ট্যান্ডার্ডটির এটির জন্য এটির প্রয়োজন হয়; আপনি স্ট্রিংাইজিং অপারেটরের সাথে সমতুল্য কৌশলও প্রয়োজন তা খুঁজে বের করার প্রবণতা।
সি 99 স্ট্যান্ডারের বিভাগ 6.10.3 'ম্যাক্রো রিপ্লেসমেন্ট', এবং 6.10.3.1 কে 'যুক্তি প্রতিস্থাপন' কভার করে।
কোনও ফাংশনের মতো ম্যাক্রোর অনুরোধের জন্য যুক্তিগুলি চিহ্নিত হওয়ার পরে, যুক্তি প্রতিস্থাপন ঘটে। প্রতিস্থাপন তালিকার একটি প্যারামিটার, যদি না পূর্বের #
বা ##
প্রাক প্রসেসিং টোকেন বা ##
প্রাকপ্রসেসিং টোকেন (নীচে দেখুন) এর পরে থাকে তবে এতে যুক্ত সমস্ত ম্যাক্রো প্রসারিত হওয়ার পরে সংশ্লিষ্ট যুক্তি দ্বারা প্রতিস্থাপন করা হয়। প্রতিস্থাপিত হওয়ার আগে, প্রতিটি যুক্তির প্রিপ্র্রোসেসিং টোকেনগুলি পুরো ম্যাক্রোকে প্রতিস্থাপন করা হয় যেন তারা বাকি প্রিপ্রসেসিং ফাইলটি গঠন করে; অন্য কোনও প্রিপ্র্রোসেসিং টোকেন উপলব্ধ নেই।
অনুরোধে NAME(mine)
যুক্তিটি 'আমার'; এটি পুরোপুরি 'আমার' তে প্রসারিত; এরপরে এটি প্রতিস্থাপনের স্ট্রিংয়ে প্রতিস্থাপন করা হয়:
EVALUATOR(mine, VARIABLE)
এখন ম্যাক্রো মূল্যায়নকারীকে আবিষ্কার করা হয়েছে, এবং যুক্তিগুলি 'আমার' এবং 'বৈকল্পিক' হিসাবে পৃথক করা হয়েছে; তারপরেরটি পুরোপুরি '3' এ প্রসারিত হবে এবং প্রতিস্থাপনের স্ট্রিংয়ের পরিবর্তে এটি করা যাবে:
PASTER(mine, 3)
এর ক্রিয়াকলাপটি অন্যান্য বিধি দ্বারা আবৃত (6.10.3.3 '' ## অপারেটর '):
যদি, কোনও ফাংশনের মতো ম্যাক্রোর প্রতিস্থাপনের তালিকায়, একটি প্যারামিটার তত্ক্ষণাত্ পূর্ববর্তী বা ##
প্রাক প্রসেসিং টোকেন দ্বারা অনুসরণ করা হয় , তবে প্যারামিটারটি যুক্তিযুক্ত প্রিপ্রোসেসিং টোকেন ক্রম দ্বারা প্রতিস্থাপিত হয়; [...]
উভয় অবজেক্টের মতো এবং ফাংশন-জাতীয় ম্যাক্রো অনুরোধগুলির জন্য, প্রতিস্থাপনের তালিকাটি আরও ম্যাক্রোর নাম প্রতিস্থাপনের জন্য পুনরায় পরীক্ষা করার আগে প্রতিস্থাপন তালিকার ##
প্রিপ্রোসেসিং টোকেনের প্রতিটি উদাহরণ মুছে ফেলা হয় এবং পূর্ববর্তী প্রিপ্রোসেসিং টোকনকে সংযুক্ত করা হয় নিম্নলিখিত প্রিপ্রোসেসিং টোকেন সহ।
সুতরাং, প্রতিস্থাপন তালিকা রয়েছে x
দ্বারা অনুসরণ ##
এবং ##
অনুসরণ y
; তাহলে আমাদের আছে:
mine ## _ ## 3
এবং ##
টোকেনগুলি অপসারণ করে এবং উভয় পক্ষের টোকেনগুলি সংহত করে ফলন করার জন্য 'খনি' কে '_' এবং '3' এর সাথে একত্রিত করে:
mine_3
এই কাঙ্ক্ষিত ফলাফল।
যদি আমরা মূল প্রশ্নটি দেখি তবে কোডটি ছিল ('কিছু' ফাংশন'-এর পরিবর্তে 'খনি' ব্যবহারের জন্য অভিযোজিত):
#define VARIABLE 3
#define NAME(fun) fun ## _ ## VARIABLE
NAME(mine)
NAME- এর পক্ষে যুক্তিটি পরিষ্কারভাবে 'আমার' এবং এটি পুরোপুরি প্রসারিত।
6.10.3.3 এর নিয়ম অনুসরণ করে আমরা পাই:
mine ## _ ## VARIABLE
যা ##
অপারেটরগুলি বাদ দিলে মানচিত্রগুলি:
mine_VARIABLE
ঠিক যেমন প্রশ্নে রিপোর্ট করা হয়েছে।
Ditionতিহ্যবাহী সি প্রিপ্রেসেসর
রবার্ট রাজার জিজ্ঞাসা করেছেন :
টোকেন পেস্টিং অপারেটর নেই এমন traditionalতিহ্যবাহী সি প্রিপ্রোসেসর দিয়ে কি কোনও উপায় আছে ##
?
হতে পারে, এবং নাও হতে পারে - এটি প্রিপ্রোসেসরের উপর নির্ভর করে। স্ট্যান্ডার্ড প্রিপ্রোসেসর এর একটি সুবিধা হ'ল এটিতে এই সুবিধাটি রয়েছে যা নির্ভরযোগ্যভাবে কাজ করে, অন্যদিকে প্রাক-প্রাক প্রিপ্রসেসরগুলির জন্য বিভিন্ন বাস্তবায়ন ছিল। একটি প্রয়োজনীয়তা হ'ল প্রিপ্রোসেসর যখন কোনও মন্তব্যে প্রতিস্থাপন করে তখন এটি কোনও স্থান তৈরি করে না কারণ এএনএসআই প্রিপ্রসেসর করতে হয়। জিসিসি (.3.৩.০) সি প্রিপ্রসেসর এই প্রয়োজনীয়তা পূরণ করে; এক্সকোড 8.2.1 এর ক্ল্যাং প্রিপ্রসেসরটি তা করে না।
যখন এটি কাজ করে, এটি কাজটি করে ( x-paste.c
):
#define VARIABLE 3
#define PASTE2(x,y) x/**/y
#define EVALUATOR(x,y) PASTE2(PASTE2(x,_),y)
#define NAME(fun) EVALUATOR(fun,VARIABLE)
extern void NAME(mine)(char *x);
মনে রাখবেন fun,
এবং এর মধ্যে কোনও স্থান নেই VARIABLE
- এটি গুরুত্বপূর্ণ কারণ যদি উপস্থিত থাকে তবে এটি আউটপুটে অনুলিপি করা হয় এবং আপনি mine_ 3
নাম হিসাবে শেষ করেন যা অবশ্যই সিন্ট্যাক্টিকভাবে বৈধ নয়। (এখন, দয়া করে আমি কি আমার চুল ফিরে পেতে পারি?)
জিসিসি 6.3.0 (চলমান cpp -traditional x-paste.c
) সহ, আমি পেয়েছি:
# 1 "x-paste.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "x-paste.c"
extern void mine_3(char *x);
এক্সকোড 8.2.1 থেকে কলঙ্ক সহ, আমি পেয়েছি:
# 1 "x-paste.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 329 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "x-paste.c" 2
extern void mine _ 3(char *x);
এই স্পেসগুলি সবকিছু লুণ্ঠন করে। আমি লক্ষ করি যে উভয় প্রিপ্রসেসরগুলি সঠিক; বিভিন্ন প্রাক-মানসম্পন্ন প্রিপ্রোসেসর উভয় আচরণকেই প্রদর্শন করেছিল, যা পোর্ট কোড দেওয়ার সময় টোকনকে একটি অত্যন্ত বিরক্তিকর এবং অবিশ্বাস্য প্রক্রিয়াযুক্ত করে তোলে। ##
স্বরলিপি সহ মানটি মূলত এটিকে সহজতর করে।
এটি করার অন্যান্য উপায়ও থাকতে পারে। তবে, এটি কাজ করে না:
#define VARIABLE 3
#define PASTER(x,y) x/**/_/**/y
#define EVALUATOR(x,y) PASTER(x,y)
#define NAME(fun) EVALUATOR(fun,VARIABLE)
extern void NAME(mine)(char *x);
জিসিসি উত্পন্ন:
# 1 "x-paste.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "x-paste.c"
extern void mine_VARIABLE(char *x);
বন্ধ, কিন্তু কোন পাশা। ওয়াইএমএমভি, অবশ্যই, আপনি ব্যবহার করছেন এমন প্রাক-মানক প্রিপ্রসেসেসরের উপর নির্ভর করে। সত্যই, যদি আপনি কোনও প্রিপ্রোসেসরের সাথে আটকে থাকেন যা সহযোগিতা করছে না, তবে প্রাক-স্ট্যান্ডার্ডের জায়গায় একটি স্ট্যান্ডার্ড সি প্রিপ্রসেসর ব্যবহার করার ব্যবস্থা করা সহজতর হবে (সাধারণত সংকলকটি যথাযথভাবে কনফিগার করার উপায় আছে) তার চেয়ে কাজ করার উপায় নিয়ে চেষ্টা করার জন্য অনেক সময় ব্যয় করা।