سؤال

لقد سُئلت سؤالاً في لغة C الليلة الماضية ولم أكن أعرف الإجابة لأنني لم أستخدم لغة C كثيرًا منذ دراستي الجامعية لذا اعتقدت أنه ربما يمكنني العثور على الإجابة هنا بدلاً من نسيانها فقط.

إذا كان لدى الشخص تعريف مثل:

#define count 1

هل يمكن لهذا الشخص العثور على اسم المتغير count باستخدام 1 الذي هو داخله؟

لم أكن أعتقد ذلك لأنني اعتقدت أن العدد سيشير إلى الرقم 1 ولكن لا أرى كيف يمكن أن يشير الرقم 1 إلى العد.

هل كانت مفيدة؟

المحلول

الجواب البسيط هو لا، لا يمكنهم ذلك.# تعريفات كهذه يتعامل معها المعالج المسبق، وهي تشير فقط إلى اتجاه واحد.بالطبع المشكلة الأخرى هي أنه حتى المترجم لن يعرف - حيث يمكن أن يشير الرقم "1" إلى أي شيء - يمكن أن يكون للمتغيرات المتعددة نفس القيمة في نفس الوقت.

نصائح أخرى

بناءً على إجابة @Cade Roux، إذا كنت تستخدم معالجًا مسبقًا #define لربط قيمة برمز، فلن يحتوي الكود على أي إشارة إلى الرمز بمجرد تشغيل المعالج المسبق:

#define COUNT (1)
...
int myVar = COUNT;
...

بعد تشغيل المعالج المسبق:

...
int myVar = (1);
...

وكما لاحظ آخرون، فإن هذا يعني في الأساس "لا"، للسبب المذكور أعلاه.

هل يمكن لهذا الشخص العثور على اسم المتغير "count" باستخدام الرقم 1 الموجود بداخله؟

لا

نظرًا لأنني متأكد من أن شخصًا أكثر بلاغة وخبرة مني سيشير إلى أن الأشياء #define'd لم يتم تجميعها في المصدر، فإن ما لديك هو ماكرو ما قبل المعالج والذي سوف يمر عبر المصدر ويغير كل مثيلات "count" "يجد مع" 1 ".

ومع ذلك، لتسليط المزيد من الضوء على السؤال الذي تم طرحه عليك، نظرًا لأن لغة C هي لغة مجمعة وصولاً إلى كود الآلة، فلن يكون لديك أبدًا التفكير والاستبطان الذي لديك مع لغة مثل Java أو C#.يتم فقدان كل الأسماء بعد التجميع ما لم يكن لديك إطار عمل مبني حول المصدر/المترجم الخاص بك للقيام ببعض الأشياء الرائعة.

يأمل هذا يساعد.(أعتذر عن التورية)

لسوء الحظ، هذا غير ممكن.

#define البيانات هي تعليمات للمعالج المسبق، كافة مثيلات count يتم استبدالها ب 1.في وقت التشغيل لا يوجد موقع ذاكرة مرتبط به count, ، ومن الواضح أن هذا الجهد غير مجدي.

حتى لو كنت تستخدم المتغيرات، بعد التجميع لن يكون هناك أي بقايا من المعرفات الأصلية المستخدمة في البرنامج.هذا ممكن بشكل عام فقط في اللغات الديناميكية.

إحدى الحيل المستخدمة في لغة C هي استخدام بناء الجملة # في وحدات الماكرو للحصول على السلسلة الحرفية لمعلمة الماكرو.

#define displayInt(val) printf("%s: %d\n",#val,val)
#define displayFloat(val) printf("%s: %d\n",#val,val)
#define displayString(val) printf("%s: %s\n",#val,val)

int main(){
  int foo=123;
  float bar=456.789;
  char thud[]="this is a string";

  displayInt(foo);
  displayFloat(bar);
  displayString(thud);

  return 0;
}

يجب أن يبدو الإخراج كما يلي:

foo: 123
bar: 456.789
thud: this is a string

#define count 1 هي فكرة سيئة للغاية، لأنها تمنعك من تسمية أي متغيرات أو حقول هيكلية count.

على سبيل المثال:

void copyString(char* dst, const char* src, size_t count) {
   ...
}

لك count سيؤدي الماكرو إلى استبدال اسم المتغير بـ 1, ، منع هذه الوظيفة من التجميع:

void copyString(char* dst, const char* src, size_t 1) {
   ...
}

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

النقطة المهمة هي أنه لا يوجد "عدد" للإشارة إلى القيمة "1".إنها مجرد عملية استبدال بسيطة/بحث تحدث قبل تم تجميع الكود بالفعل.

سأترك هذا قابلاً للتحرير لشخص يعرف لغة C حقًا لتصحيحه.

count ليس متغيرا.لا يوجد لديه مساحة تخزين مخصصة له ولا يوجد إدخال في جدول الرموز.إنه ماكرو يتم استبداله بواسطة المعالج المسبق قبل تمرير الكود المصدري إلى المترجم.

إذا لم تكن تطرح السؤال الصحيح تمامًا، فهناك طريقة للحصول على الاسم باستخدام وحدات الماكرو:

#define SHOW(sym) (printf(#sym " = %d\n", sym))
#define count 1

SHOW(count); // prints "count = 1"

ال # يقوم عامل التشغيل بتحويل وسيطة ماكرو إلى سلسلة حرفية.

#define هو توجيه ما قبل المعالج، وبالتالي فهو ليس "متغيرًا"

ما لديك هناك في الواقع ليس متغيرًا، بل هو توجيه ما قبل المعالج.عندما تقوم بتجميع التعليمات البرمجية، سيمر المعالج المسبق ويستبدل جميع مثيلات الكلمة "count" في هذا الملف بـ 1.

قد تتساءل عما إذا كنت أعرف 1 هل يمكنني العثور على هذا العد يشير إليه؟لا.لأن العلاقة بين أسماء المتغيرات وقيمها ليست تناقضًا، فلا مجال للرجوع عنها.يعتبر

int count = 1;
int count2 = 1;

قانوني تمامًا ولكن ما الذي يجب علي حله؟

بشكل عام، لا.

أولاً، #define ليس متغيرًا، بل هو ماكرو معالج مسبق للمترجم.

بحلول الوقت الذي تبدأ فيه المرحلة الرئيسية للمترجم، يتم استبدال الاسم بالقيمة، ولن يكون الاسم "count" موجودًا في أي مكان في الكود الذي تم تجميعه.

بالنسبة للمتغيرات، ليس من الممكن العثور على أسماء المتغيرات في كود C في وقت التشغيل.لا يتم الاحتفاظ بهذه المعلومات.على عكس لغات مثل Java أو C#، لا تحتفظ لغة C بالكثير من البيانات الوصفية على الإطلاق، في عمليات التحويل البرمجي وصولاً إلى لغة التجميع.

تتم معالجة التوجيهات التي تبدأ بـ "#" بواسطة المعالج المسبق الذي عادةً ما يقوم باستبدال النص قبل تمرير الكود إلى المترجم "الحقيقي".على هذا النحو، لا يوجد متغير يسمى count، يبدو الأمر كما لو أن جميع سلاسل "count" في شفرتك قد تم استبدالها بطريقة سحرية بالسلسلة "1".

لذا، لا، لا توجد طريقة للعثور على هذا "المتغير".

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

لذا فإن الجواب هو لا.

إذا كانوا ينظرون إلى الكود المصدري للغة C (والذي سيكونون موجودين في مصحح الأخطاء)، فسوف يرون شيئًا كهذا

int i = count;

وعند هذه النقطة، يمكنهم البحث مرة أخرى والعثور على الخط

#define count 1

ومع ذلك، إذا كان كل ما لديهم هو المتغير iDontKnowWhat، ويمكنهم رؤيته يحتوي على 1، فلا توجد طريقة لتتبع ذلك مرة أخرى إلى "العدد".

لماذا؟لأن #define يتم تقييمه في وقت المعالجة المسبقة، والذي يحدث حتى قبل الترجمة (على الرغم من أنه يمكن اعتباره المرحلة الأولى من الترجمة بالنسبة للجميع تقريبًا).وبالتالي فإن الكود المصدري هو الشيء الوحيد الذي يحتوي على أي معلومات حول "العدد"، مثل معرفة وجوده على الإطلاق.بحلول الوقت الذي يقوم فيه المترجم بالبحث، يتم استبدال كل إشارة إلى "count" بالرقم "1".

إنه ليس مؤشرًا، إنه مجرد استبدال سلسلة/رمز مميز.يستبدل المعالج المسبق كافة التعريفات قبل تجميع التعليمات البرمجية الخاصة بك.تشتمل معظم المترجمات على -E أو وسيطة مشابهة لإصدار تعليمات برمجية مجمعة مسبقًا، حتى تتمكن من رؤية شكل التعليمات البرمجية بعد معالجة كافة التوجيهات.

بالنسبة لسؤالك بشكل مباشر، لا توجد طريقة لمعرفة أنه يتم استبدال الرمز المميز في التعليمات البرمجية.لا يستطيع الكود الخاص بك حتى معرفة الفرق بين (العدد == 1) و (1 == 1).

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

ماذا تقصد ب "العثور"؟

الخط

#define count 1

يحدد رمز "العد" الذي له القيمة 1.

ستستبدل الخطوة الأولى من عملية الترجمة (تسمى المعالجة المسبقة) كل تكرار لعدد الرموز بـ 1 بحيث إذا كان لديك:

if (x > count) ...

سيتم استبداله بـ:

if (x > 1) ...

إذا فهمت هذا، فقد ترى لماذا لا معنى لعبارة "العثور على العدد".

ربما كان الشخص الذي يطرح السؤال (هل كان سؤالاً للمقابلة؟) يحاول جعلك تفرق بين استخدام #define ثوابت مقابل التعدادات.على سبيل المثال:

#define ZERO 0
#define ONE 1
#define TWO 2

ضد

enum {
  ZERO,
  ONE,
  TWO
};

نظرا للكود:

x = TWO;

إذا كنت تستخدم التعدادات بدلاً من #defines، فستكون بعض مصححات الأخطاء قادرة على إظهار الشكل الرمزي للقيمة، TWO، بدلاً من القيمة الرقمية 2 فقط.

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