سؤال

لدي برنامج صغير والذي يقارن

(1) Sizeof ، (2) numeric_limits :: الأرقام ، (3) ونتائج حلقة

في محاولة للتأكد من أنهم جميعًا يبلغون عن نفس الشيء فيما يتعلق بحجم "أنواع int" في أي تطبيق C++.ومع ذلك، لأنني لا أعرف شيئًا عن الأجزاء الداخلية لـ sizeof، يجب أن أتساءل عما إذا كانت تقوم فقط بالإبلاغ عن numeric_limits::digits.شكرًا

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

المحلول

على الأرجح sizeof() في معظم المترجمين، يتسبب المترجم في البحث عن النوع المحدد (أو نوع الكائن) في جدول النوع الداخلي الخاص به وإدراج حرفي للحجم المحدد لهذا النوع في الكود الذي ينشئه. سيحدث هذا في وقت الترجمة, ، وليس وقت التشغيل.

للإجابة على السؤال في التعليقات، لا يوجد أي وصول محدد باللغة إلى الأجزاء الداخلية للمترجم في C++ (خارج أشياء مثل sizeof() نفسها بالطبع).اللغة الوحيدة المشابهة التي أعرفها والتي تتيح لك القيام بأشياء كهذه هي Ada، التي توفر كما هي لكتابة أدوات تحليل التعليمات البرمجية المستقلة عن المترجم.

نصائح أخرى

ال sizeof عامل التشغيل هو بناء وقت الترجمة الذي من خلاله يقوم المترجم بالإبلاغ عن الحجم، بالبايت، الذي سيشغله مثيل النوع المحدد في الذاكرة.

من الصعب إعطاء إجابة عامة "هذه هي الطريقة التي يعمل بها sizeof" لأنها خاصة بكل تطبيق مترجم.في عام على الرغم من أنه يعمل عن طريق حساب حجم كل حقل من النوع وإضافته معًا مع مراعاة المحاذاة.

على سبيل المثال، إليك مجموعة معقولة من المخرجات [1]

struct S1 {
  int field1;
  int field2;
};

struct S2 {
  int field1;
  bool field2;
  int field3;
}

sizeof(S1) == 8
sizeof(S2) == 12;

السبب وراء قيام العديد من المترجمين بالإبلاغ عن حجم S2 بدلاً من 12 بدلاً من 9، يجب أن يأخذ في الاعتبار مشكلات المحاذاة ومن ثم إدراج 3 بايت لتعويض الفجوة بين field2 و field3

[1] ملاحظة:قلت معقول غير مضمون :).تتمتع مجمعات لغة C بمرونة كبيرة في الأحجام ومن المستحيل تقريبًا تحديد تفاصيل حول الأحجام دون معرفة المترجم الذي تعمل معه

ليس هناك الكثير من الداخلية ل sizeof;إنه عامل تشغيل مدمج يُبلغ عن حجم المعامل الخاص به (إما تعبيرًا أو نوعًا) بالبايت.

الكود الخاص بك معقد إلى حد ما - ويستخدم typeid يتركني أتساءل...

لدي برنامج ثنائي اللغة (مكتوب في المجموعة الفرعية C من C++) ينتج إجابات مثل:

 1 = sizeof(char)
 1 = sizeof(unsigned char)
 2 = sizeof(short)
 2 = sizeof(unsigned short)
 4 = sizeof(int)
 4 = sizeof(unsigned int)
 8 = sizeof(long)
 8 = sizeof(unsigned long)
 4 = sizeof(float)
 8 = sizeof(double)
16 = sizeof(long double)
 8 = sizeof(size_t)
 8 = sizeof(ptrdiff_t)
 8 = sizeof(time_t)
 8 = sizeof(void *)
 8 = sizeof(char *)
 8 = sizeof(short *)
 8 = sizeof(int *)
 8 = sizeof(long *)
 8 = sizeof(float *)
 8 = sizeof(double *)
 8 = sizeof(int (*)(void))
 8 = sizeof(double (*)(void))
 8 = sizeof(char *(*)(void))
 1 = sizeof(struct { char a; })
 2 = sizeof(struct { short a; })
 4 = sizeof(struct { int a; })
 8 = sizeof(struct { long a; })
 4 = sizeof(struct { float a; })
 8 = sizeof(struct { double a; })
16 = sizeof(struct { char a; double b; })
16 = sizeof(struct { short a; double b; })
16 = sizeof(struct { long a; double b; })
 4 = sizeof(struct { char a; char b; short c; })
16 = sizeof(struct { char a; char b; long c; })
 4 = sizeof(struct { short a; short b; })
 6 = sizeof(struct { char a[3]; char b[3]; })
 8 = sizeof(struct { char a[3]; char b[3]; short c; })
16 = sizeof(struct { long double a; })
32 = sizeof(struct { char a; long double b; })

(تم إنتاج هذا بواسطة G++ 4.6.0 على MacOS X 10.6.7 - تجميع 64 بت).الكود الذي استخدمته هو:

#ifdef __cplusplus
#define __STDC_CONSTANT_MACROS
#endif /* __cplusplus */

#include <stdio.h>
#include <time.h>
#include <stddef.h>
#if __STDC_VERSION__ >= 199901L || HAVE_INTTYPES_H
#include <inttypes.h>
#endif /* __STDC_VERSION__ */

/* Using the simple C code in SPRINT() for structures leads to complaints from G++ */
/* Using the code in TPRINT() for pointers to functions leads to other complaints */
#define TPRINT(x)   do { typedef x y; printf("%2u = sizeof(" #x ")\n", (unsigned int)sizeof(y)); } while (0)
#define SPRINT(x)   printf("%2u = sizeof(" #x ")\n", (unsigned int)sizeof(x))

int main(void)
{
    /* Basic Types */
    SPRINT(char);
    SPRINT(unsigned char);
    SPRINT(short);
    SPRINT(unsigned short);
    SPRINT(int);
    SPRINT(unsigned int);
    SPRINT(long);
    SPRINT(unsigned long);

    SPRINT(float);
    SPRINT(double);
    SPRINT(long double);
    SPRINT(size_t);
    SPRINT(ptrdiff_t);
    SPRINT(time_t);

    /* Fancy integers */
#if __STDC_VERSION__ >= 199901L || HAVE_LONG_LONG
    SPRINT(long long);
    SPRINT(unsigned long long);
#endif /* __STDC_VERSION__ || HAVE_LONG_LONG */
#if __STDC_VERSION__ >= 199901L || HAVE_INTTYPES_H
    SPRINT(uintmax_t);
#ifdef INT8_MAX
    SPRINT(int8_t);
#endif
#ifdef INT16_MAX
    SPRINT(int16_t);
#endif
#ifdef INT32_MAX
    SPRINT(int32_t);
#endif
#ifdef INT64_MAX
    SPRINT(int64_t);
#endif
#ifdef INT128_MAX
    SPRINT(int128_t);
#endif
    SPRINT(int_least8_t);
    SPRINT(int_least16_t);
    SPRINT(int_least32_t);
    SPRINT(int_least64_t);
    SPRINT(int_fast8_t);
    SPRINT(int_fast16_t);
    SPRINT(int_fast32_t);
    SPRINT(int_fast64_t);
    SPRINT(uintptr_t);
#endif /* __STDC_VERSION__ || HAVE_INTTYPES_H */

    /* Pointers */
    SPRINT(void *);
    SPRINT(char *);
    SPRINT(short *);
    SPRINT(int *);
    SPRINT(long *);
    SPRINT(float *);
    SPRINT(double *);

    /* Pointers to functions */
    SPRINT(int (*)(void));
    SPRINT(double (*)(void));
    SPRINT(char *(*)(void));

    /* Structures */
    TPRINT(struct { char a; });
    TPRINT(struct { short a; });
    TPRINT(struct { int a; });
    TPRINT(struct { long a; });
    TPRINT(struct { float a; });
    TPRINT(struct { double a; });
    TPRINT(struct { char a; double b; });
    TPRINT(struct { short a; double b; });
    TPRINT(struct { long a; double b; });
    TPRINT(struct { char a; char b; short c; });
    TPRINT(struct { char a; char b; long c; });
    TPRINT(struct { short a; short b; });
    TPRINT(struct { char a[3]; char b[3]; });
    TPRINT(struct { char a[3]; char b[3]; short c; });
    TPRINT(struct { long double a; });
    TPRINT(struct { char a; long double b; });
#if __STDC_VERSION__ >= 199901L || HAVE_LONG_LONG
    TPRINT(struct { char a; long long b; });
#endif /* __STDC_VERSION__ */
#if __STDC_VERSION__ >= 199901L || HAVE_INTTYPES_H
    TPRINT(struct { char a; uintmax_t b; });
#endif /* __STDC_VERSION__ || HAVE_INTTYPES_H */

    return(0);
}

لا أتذكر بالضبط لماذا اضطررت إلى القيام بهذا العبث __STDC_CONSTANT_MACROS و SPRINT() ضد TPRINT(), ، ولكن يبدو أن هذا هو ما هو مطلوب (في مارس 2010) لجعل الكود ثنائي اللغة.

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