سؤال

على سبيل المثال، هل من الممكن ما يلي:

#define definer(x) #define #x?
هل كانت مفيدة؟

المحلول

على الرغم من أن بناء الجملة الخاص بك غير صالح ، إلا أن الإجابة على سؤالك هي نعم تقنيًا. ولكن لا يمكن إنجازه إلا من خلال الحيل السيئة التي تجعل الكود غير قابل للقراءة ولا يمكن صيانته.

أنظر أيضا: http://www.ioccc.org/years.html#1995_vanschnitz و http://www.ioccc.org/years.html#2004_vik2

نصائح أخرى

لا ، لا يمكنك فعل ذلك.
الجنيه (#) الرمز له معنى مختلف أثناء التعريف. هذا يعني - إذا كانت هذه وسيطة ، اجعلها سلسلة من خلال الاقتباس.

لا يمكنك عش التوجيهات قبل المعالج. لحسن الحظ ، ليس من الضروري تقريبًا. إذا كنت بحاجة حقًا إلى هذا النوع من القوة ، فمن المؤكد أنك ستكون أفضل حالًا مع معالج مسبق آخر تقوم بتشغيله قبل تسليم الكود إلى برنامج التحويل البرمجي C. فمثلا:

sed 's/@CUSTOMER@/J. Random Person/' foo.c.in > foo.c
cc foo.c

خدعة أخرى مفيدة هي عزل الخداع في ملف رأس واحد ، والذي يتم إنشاؤه بواسطة برنامج تكتبه بنفسك:

./generate-trickery --greet 'J. Random Person' > foo.h

أين سيبدو foo.h مثل شيء مثل هذا:

#define GREET(x) ("J. Random Person greets you, " #x)

إذا قمت بربط هذا مع Makefile ، أو بعض الأتمتة الأخرى ، فسيكون ذلك سلسًا إلى حد كبير ولا يتجول في تطورك كثيرًا.

لا ، لا يمكنك فعل ذلك.

يمكنك الرجوع إلى ماكرو من الآخر ، لكن لا يمكنك تحديد ماكرو من آخر.

إذا كنت تحاول إنشاء مقطع من تعليمات برمجية للمعالج المسبق يمكن استدعاؤه عدة مرات لتنفيذ أشياء مختلفة قليلاً، فإحدى الطرق (الفظيعة إلى حد ما) التي يمكنك من خلالها القيام بذلك هي عزل التعليمات البرمجية في جزء واحد .h الملف الذي قمت بعد ذلك #include عدة مرات.الفكرة هي أنه في كل مرة تقوم فيها #include الملف الذي "تستدعيه روتينك" - "تمرير الوسائط" أولاً #defineمعالجة بعض ثوابت المعالج المسبق التي يشير إليها الملف المضمن.

أحد الأماكن التي رأيت فيها هذا مفيدًا هو إنشاء تعدادات "ذكية" يمكن تحويلها من/إلى نماذجها "السلسلة" (وهو أمر مفيد للإدخال/الإخراج).قمت بإنشاء .h ملف يحتوي على سبيل المثال

ENUMVAL(foo)
ENUMVAL(bar)
ENUMVAL(baz)

وبعد ذلك في وقت لاحق #include هذا الملف مرتين:مرة واحدة حيث ENUMVAL() يتم تعريفه بطريقة لإنشاء enum إعلان، ومرة ​​واحدة متى ENUMVAL() يتم تعريفه بطريقة تنتج مجموعة من الأسماء المتسلسلة.ومن خلال القيام بذلك بهذه الطريقة، لن تحتاج إلى تحديد قائمة الرموز الفعلية أكثر من مرة.

#define definer(x) #define #x?

#x هو سلسلة من x. لا يمكنك #تحديد الرمز المميز للسلسلة. (#تحديد "فو".) يجب أن يكون معرفًا A-ZA-Z0-9 _]* رمز.

أنت لا يمكن عش #تعريف هكذا. لا يمكن أن يكون لديك #Define في #Define.

أنت يستطيع لديك #if inside #if.

#ifdef FOO

#ifdef BAR
 ...
#else // BAR
 ...
#endif // BAR

#else // FOO
 ...
#endif //FOO

أنت أيضًا محدود إلى حد ما فيما يتعلق بالتعبيرات التي يمكنك استخدامها في وحدات الماكرو #F. ولكن يمكنك في بعض الأحيان العمل حول ذلك. فمثلا:

        /* Use CONCATENATE_4_AGAIN to expand the arguments to CONCATENATE_4 */
#define CONCATENATE_4(      a,b,c,d)  CONCATENATE_4_AGAIN(a,b,c,d)
#define CONCATENATE_4_AGAIN(a,b,c,d)  a ## b ## c ## d

    /* Creates a typedef that's legal/illegal depending on EXPRESSION.       *
     * Note that IDENTIFIER_TEXT is limited to "[a-zA-Z0-9_]*".              *
     * (This may be replaced by static_assert() in future revisions of C++.) */
#define STATIC_ASSERT( EXPRESSION, IDENTIFIER_TEXT)                     \
  typedef char CONCATENATE_4( static_assert____,      IDENTIFIER_TEXT,  \
                              ____failed_at_line____, __LINE__ )        \
            [ (EXPRESSION) ? 1 : -1 ]

بالإضافة إلى شيء مثل:

STATIC_ASSERT( sizeof(int1) == 1, sizeof_int1_equal_1 );

(نعم ، أنا أعرف عنها #تضمنu003Cstdint.h>. إنه مجرد مثال.)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top