it-swarm.dev

cout << بحرف char * يطبع السلسلة ، وليس قيمة المؤشر

هذه:

const char * terry = "hello";
cout<<terry;

طباعة hello بدلاً من عنوان الذاكرة الخاص بـ 'h'. لماذا يحدث هذا؟

51
Mr.Puff

السبب في ذلك هو أن std::cout ستتعامل مع char * كمؤشر على (الحرف الأول من) سلسلة C نمط وطباعتها على هذا النحو. إذا كنت تريد عنوان بدلاً من ذلك ، يمكنك فقط إلقاءها على مؤشر يعامل ليس بهذه الطريقة ، مثل:

cout << (void *) terry;

(أو استخدم ملف الكود const void * إذا كنت قلقًا بشأن التخلص من الثبات ، وهو أمر لا يمثل مشكلة في هذه الحالة بالذات).


إذا كنت أكثر نقاءًا من البراغماتيين ، فيمكنك أيضًا استخدام C++ static_cast ، على غرار:

cout << static_cast <const void *> (terry);

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

#include <iostream>
int main (void) {
    const char *terry = "hello";
    std::cout << terry << '\n';
    std::cout << (void *) terry << '\n';
    std::cout << (const void *) terry << '\n';
    std::cout << static_cast<const void *> (terry) << '\n';
    return 0;
}

الإخراج (قد يكون العنوان مختلفًا في بيئتك):

hello
0x8048870
0x8048870
0x8048870

لاحظ أنه عند استخدام static_cast ، يجب أن تتأكد من أنك لا تحاول التخلص من الثبات باستخدام static_cast <void *> (هذا هو const_cast). هذا أحد عمليات الفحص التي أجراها الممثلون الجدد في C++ ولا يلقي هذا النمط القديم هذا القيد.

68
paxdiablo

يتم تحميل عامل التشغيل << على std::cout. يعتمد سلوكها على نوع المعامل الصحيح. (إنها في الواقع عدة وظائف مختلفة ، وكلها مسماة operator<< ؛ المترجم يقرر أي واحد لاستدعاء.)

إذا أعطيته رمزًا char* أو const char* ، فسيتعامل مع المعامل كمؤشر على (الحرف الأول من) سلسلة نمط C ، ويطبع محتويات تلك السلسلة:

const char * terry = "hello";
cout << terry; // prints "hello"

إذا أعطيتها قيمة char ، فإنها تطبع تلك القيمة كحرف:

cout << *terry;   // prints "h"
cout << terry[0]; // the same

إذا قمت بإعطائه مؤشر من النوع void* ، فإنه يطبع قيمة المؤشر (بطريقة معينة محددة بالتنفيذ ، عادةً ست عشرية):

cout << static_cast<const void*>(terry); // prints something like 0x4008e4

تعتبر معاملة char* أو const char* كمؤشر لسلسلة C نمط حالة خاصة ، والحالة الوحيدة (التي يمكنني التفكير فيها) التي تسبب operator<< في طباعة شيء آخر غير قيمة المعامل. يرجع السبب في ذلك إلى جذور C++ في C ، والذي لا يحتوي على نوع "سلسلة" ويتعامل مع السلاسل عبر مؤشرات char*.

هناك العديد من الأحمال الزائدة الأخرى لـ operator<< ، ولأنواع الأعداد الصحيحة والأرقام الفاصلة العائمة المختلفة ، و std::string ، وهكذا دواليك.

18
Keith Thompson

يجب عليك تغيير الكود الخاص بك إلى هذا:

cout << static_cast<const void*>(terry);

المشكلة هي أن عامل التشغيل << محمّل بالمؤشرات إلى سلاسل على غرار C لطباعة محتوى السلسلة. إذا قمت بنقلها إلى المؤشر الخام بدلاً من ذلك ، سيكون لديك السلوك الافتراضي لطباعة المؤشر باستخدام iostreams كما تريد.

9
sasha.sochka

يتم تحميل cout بشكل زائد بحيث عندما تمنحها حرفًا * ، ستتم طباعته كمؤشر إلى سلسلة نمط C. لذلك ، فإنه يطبع الأحرف حتى يصل إلى حرف إنهاء فارغ.

إذا كنت تستخدم printf بدلاً من cout ، فسترى العنوان. يمكنك أيضًا إلقاء المؤشر على نوع آخر ، قل (باطل *) وستحصل أيضًا على العنوان.

1
Richard Fung

يتم تعريف std::cout على أنه std::ostream مع هذا تعريف operator<<.

أبرز هذا الخط:

template< class CharT, class Traits >
basic_ostream<CharT,Traits>& operator<<( basic_ostream<CharT,Traits>& os,
                                     const char* s );

يتم تحديد ذلك عند استخدام << مع وسيطة من النوع char*.

حالة أي نوع مؤشر غير شار آخر يذهب هنا :

basic_ostream& operator<<( const void* value );

يستمر هذا إلى std::num_put الذي يتم إجراؤه لتنسيق القيم الرقمية. لذلك ، يتم interpreted المؤشر عدديًا مثل %p في وظائف التنسيق C.

1
IllidanS4