ما هو الاستخدام السليم للطباعة لعرض المؤشرات مبطن مع 0S

StackOverflow https://stackoverflow.com/questions/1255099

  •  12-09-2019
  •  | 
  •  

سؤال

في ج، أود استخدام Printf لعرض المؤشرات، وذلك بحيث يصطفون بشكل صحيح، أود أن أعدهم مع 0s.

كان تخميني أن الطريقة المناسبة للقيام بذلك كانت:

printf ("٪ 016p"، PTR)؛

هذا يعمل، ولكن هذه الخليجية تشكو مع الرسالة التالية:

تحذير: '0' يستخدم مع تنسيق "٪ P" GNU_PRINTF

لقد غوتشن قليلا لذلك، والخيط التالي هو على نفس الموضوع، ولكن لا يعطي حل حقا.

http://gcc.gnu.org/ml/ml/gcc-bugs/2003-05/msg00484.html.

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

حتى هنا هو السؤال المزدوج:

  • هل فهمي صحيح أن هذا السلوك غير محدد بواسطة معيار C99؟
  • إذا كان الأمر كذلك، هل هناك طريقة قياسية معتمدة أو محمولة للقيام بذلك؟
هل كانت مفيدة؟

المحلول

#include <inttypes.h>

#include <stdint.h>

printf("%016" PRIxPTR "\n", (uintptr_t)ptr);

لكنه لن يطبع المؤشر في طريقة تعريف التنفيذ DEAD:BEEF ل 8086 وضع مجزأ).

نصائح أخرى

يستخدم:

#include <inttypes.h>

printf("0x%016" PRIXPTR "\n", (uintptr_t) pointer);

أو استخدم متغير آخر من وحدات الماكرو من هذا الرأس.

لاحظ أيضا أن بعض تطبيقات printf() طباعة0xأمام المؤشر؛ الآخرين لا (وكلاهما صحيح وفقا لمعيار C).

الوحيد المحمولة طريقة لطباعة قيم المؤشر هي استخدام "%p" المواصفات، التي تنتج الإخراج المحدد بالتنفيذ. (تحويل إلى uintptr_t واستخدام PRIxPTR من المرجح أن تعمل، ولكن (أ) uintptr_t تم تقديمه في C99، لذلك قد لا يدعمها بعض المترجمين، و (ب) غير مضمون موجودة حتى في C99 (قد لا يكون هناك نوع صحيح كبير بما يكفي لعقد جميع قيم المؤشر الممكنة.

لذلك استخدام "%p" مع sprintf() (أو snprintf(), ، إذا كان لديك) للطباعة إلى سلسلة، ثم طباعة حشوة السلسلة مع الفراغات الرائدة.

مشكلة واحدة هي أنه لا توجد طريقة جيدة حقا لتحديد الحد الأقصى لطول السلسلة الناتجة عن طريق "%p".

من المسلم به أن هذا أمر غير مريح (رغم أنه بالطبع يمكنك لفه في وظيفة). إذا كنت لا تحتاج إلى إمكانية نقل 100٪، فقد استخدمت أبدا نظام تم صب المؤشر unsigned long وطباعة النتيجة باستخدام "0x%16lx" لن تعمل. [تحديث: نعم لدي. يحتوي Windows 64 بت على مؤشرات 64 بت و 32 بت unsigned long.] (أو يمكنك استخدام "0x%*lx" وحسب العرض، ربما شيء مثل sizeof (void*) * 2. وبعد إذا كنت حقا باركان، فيمكنك حساب النظم CHAR_BIT > 8, ، لذلك ستحصل على أكثر من 2 أرقام المائة لكل بايت.)

هذه الإجابة مشابهة للواحدة السابقة في وقت سابق https://stackoverflow.com/a/1255185/1905491. ولكن أيضا يأخذ العرض المحتمل في الاعتبار (كما هو موضح بواسطة https://stackoverflow.com/a/6904396/1905491. التي لم أتعرف عليها حتى تم تقديم إجابتي أدناه؛). ستخطى ما يلي مقرزا مؤشرات كحرف عرافة مرور 8 مرتين على آلات سان * حيث يمكن تمثيلها بمقدار 32 بت، 16 في 64B و 4 على أنظمة 16B.

#include <inttypes.h>
#define PRIxPTR_WIDTH ((int)(sizeof(uintptr_t)*2))

printf("0x%0*" PRIxPTR, PRIxPTR_WIDTH, (uintptr_t)pointer);

لاحظ استخدام حرف العلامة النجمية لجلب العرض من خلال الوسيطة التالية، وهو في C99 (ربما قبل؟)، ولكن نادرا ما ينظر إليه "في البرية". هذا أفضل من استخدام p التحويل لأن الأخير يتم تعريف التنفيذ.

* المعيار يسمح uintptr_t لتكون أكبر من الحد الأدنى، لكنني أفترض أنه لا يوجد أي تنفيذ لا يستخدم الحد الأدنى.

من السهل حلها إذا قمت بإلقاء المؤشر على نوع طويل. المشكلة هي أن هذا لن يعمل على جميع المنصات لأنه يفترض أنه يمكن أن يتناسب المؤشر داخل فترة طويلة، وأنه يمكن عرض مؤشر في 16 حرفا (64 بت). هذا صحيح على معظم المنصات.

لذلك سيصبح:

printf("%016lx", (unsigned long) ptr);

كما يوحي رابطك بالفعل، فإن السلوك غير محدد. لا أعتقد أن هناك طريقة محمولة للقيام بذلك حيث يعتمد٪ P نفسه على النظام الأساسي الذي تعمل عليه. يمكنك بالطبع فقط يلقي المؤشر إلى Int ويعرضه في عرافة:

printf("0x%016lx", (unsigned long)ptr);

ربما سيكون هذا مثيرا للاهتمام (من جهاز Windows 32 بت، باستخدام MINGW):

rjeq@RJEQXPD /u
$ cat test.c
#include <stdio.h>

int main()
{
    char c;

    printf("p: %016p\n", &c);
    printf("x: %016llx\n", (unsigned long long) (unsigned long) &c);

    return 0;
}

rjeq@RJEQXPD /u
$ gcc -Wall -o test test.c
test.c: In function `main':
test.c:7: warning: `0' flag used with `%p' printf format

rjeq@RJEQXPD /u
$ ./test.exe
p:         0022FF77
x: 000000000022ff77

كما ترون، فإن منصات الإصدار٪ P مع الأصفار إلى حجم المؤشر، ثم المسافات إلى الحجم المحدد، في حين أن استخدام٪ x والسمات (محطات الملصقات والتنسيق غير قابلية للغاية) يستخدم فقط الأصفار فقط.

لاحظ أنه إذا كان يطبع المؤشر بادئة "0x"، فستحتاج إلى استبدال "٪ 018 بكسل" للتعويض.

عادة ما أستخدم٪ X لعرض المؤشرات. أفترض أنه غير محمول إلى أنظمة 64 بت، لكنه يعمل بشكل جيد لمدة 32 نقطة.

سأكون مهتما برؤية ما هي الإجابات هناك الحلول المحمولة, ، منذ تمثيل المؤشر ليس بالضبط المحمولة.

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