ทำไม const char * ไม่ต้องการตัวชี้ไปยังที่อยู่หน่วยความจำ


18

นี่อาจเป็นคำถามง่าย ๆ แต่ทำไม const char * ไม่จำเป็นต้องระบุที่อยู่หน่วยความจำ

ตัวอย่าง:

const char* a = "Anthony";

และไม่:

const char *a = // Address to const char

เหมือนประเภทอื่น ๆ


8
อะไรทำให้คุณคิดว่าตัวอักษรสตริงไม่มีที่อยู่หน่วยความจำ
user207421

2
ตกลง ฉันไม่คิดว่าจะมีใครถามคำถามนี้เพื่อรู้ว่าหมวดหมู่คุณค่ามีอยู่จริง
user4581301

13
โปรดอย่าถามคำถามที่ติดแท็กด้วย C และ C ++ ในขณะที่เราสามารถสังเกตเห็นคำตอบคือตอนนี้เฉพาะ C ++ และความคิดเห็นตกรางอีกครั้งเกี่ยวกับความแตกต่างระหว่างทั้งสองภาษา มีความแตกต่างมากมายตอนนี้มันยากที่จะถามคำถามที่จริงมีคำตอบที่ถูกต้องเหมือนกันสำหรับทั้งสองภาษา ตัดสินใจเลือกภาษาที่คุณต้องการใช้ก่อนถาม
larkey

คำตอบ:


26

คุณสามารถจินตนาการประกาศนี้

const char* a = "Anthony";

วิธีดังต่อไปนี้

const char string_literal[] = "Anthony";

const char *a = string_literal;

นั่นคือคอมไพเลอร์สร้างอาร์เรย์ของตัวอักษรที่มีระยะเวลาการจัดเก็บข้อมูลแบบคงที่ร้านค้าสตริง"Anthony"และที่อยู่ของตัวอักษรตัวแรกของอาร์เรย์ (เนื่องจากการแปลงโดยนัยของ designators อาร์เรย์จะชี้ไปยังตัวอักษรแรกของพวกเขา) aได้รับมอบหมายให้ตัวชี้

นี่คือโปรแกรมสาธิตที่แสดงให้เห็นว่าตัวอักษรสตริงเป็นอาร์เรย์อักขระ

#include <iostream>
#include <type_traits>

decltype( auto ) f()
{
    return ( "Anthony" );
}

template <size_t N>
void g( const char ( &s )[N] )
{
    std::cout << s << '\n';
}

int main() 
{
    decltype( auto ) r = f();

    std::cout << "The size of the referenced array is "
              << std::extent<std::remove_reference<decltype( r )>::type>::value
              << '\n';

    g( r );

    return 0;
}

ผลลัพธ์ของโปรแกรมคือ

The size of the referenced array is 8
Anthony

ขนาดของตัวอักษรสตริง (ของอาร์เรย์ที่เก็บสายอักขระตัวอักษร) เท่ากับ8เพราะสตริงยังรวมถึงยุติศูนย์อักขระ \0''

ในโปรแกรมสาธิตการแสดงออก

std::extent<std::remove_reference<decltype( r )>::type>::value

อาจถูกแทนที่ด้วยเพียงการแสดงออก

sizeof( r )

5

เหตุใด const char จึงไม่ต้องการที่อยู่หน่วยความจำให้ชี้ไปที่ *

มันทำ

C-string เหมือนตัวอักษร

"Anthony"

จะสลายตัวไปยังที่อยู่ของตน 1 เซนต์ตัวอักษร ชอบ BTW; อาร์เรย์ใน C ใด ๆ


โดยเฉพาะอย่างยิ่งมันเป็นประเภทconst char[8](ใน C ++, อาจจะchar [8]อยู่ใน C, ไม่แน่ใจ) และชอบอาร์เรย์ในตัวทั้งหมดเมื่อใช้มันเป็นค่าที่จะสลายตัวชี้ไปยังองค์ประกอบแรก
Nikos C.

@ NikosC: ขอบคุณที่เตือนฉันถึงกริยาวิเศษที่สำคัญที่สุดในบริบทนี้! ;)
alk

ขอบคุณสำหรับคำตอบ! ฉันสงสัยว่าจะได้รับหน่วยความจำจากที่ไหน
Weidelix

1
พูดไม่ได้สำหรับ C แต่ฉันค่อนข้างมั่นใจว่า C ++ ไม่ได้ระบุตำแหน่งที่จะต้องจัดเก็บสัญญ เพิ่งไปขุด หากมีกฎมันจะฝังอยู่ที่ไหนสักแห่งที่แปลกและอยู่ไกลจากการพูดถึง "สตริงตัวอักษร"
user4581301

2
@NikosC char [8]ใน C: c-faq.com/ansi/strlitnotconst.html
David Ranieri

1

มันต้องการที่อยู่หน่วยความจำและมันก็มีที่อยู่หน่วยความจำ ในตัวอย่างของคุณเป็นเพียงที่อยู่หน่วยความจำของจุดเริ่มต้นของสตริง มันเหมือนกับตัวแปรอาเรย์อื่น ๆ ที่เริ่มต้น ณ เวลาคอมไพล์เช่น "int array [] = {0, 1, 2, 3};"

หากคุณใช้โปรแกรมแก้ไขไบนารีเพื่อดูไฟล์ปฏิบัติการคุณจะเห็นสตริง "Anthony" อยู่ในนั้น หากคุณใส่บรรทัด "printf (" a อยู่ที่% p \ n ", (void *) a);" ในโปรแกรมของคุณจากนั้นรวบรวมและเรียกใช้คุณจะเห็นที่อยู่


0

"ทำไมconst char*ไม่ต้องการตัวชี้ไปยังที่อยู่หน่วยความจำ"

ในความเป็นจริงมันไม่จำเป็นต้องมีที่อยู่หน่วยความจำชี้ไปที่

const char* aหมายความว่าaเป็นตัวชี้ไปยังตัวอักษรสตริงหรือค่าคงที่ตัวละคร

ตัวชี้เสมอต้องมีที่อยู่ที่จะชี้ไปเพราะมันเป็นธรรมชาติของตัวชี้ไปยังจุดที่จะเป็นวัตถุที่เฉพาะเจาะจงในหน่วยความจำ ดังนั้นaและตัวชี้อื่น ๆconst charก็ทำเช่นกัน

สตริงตัวอักษรชอบ"Hi My Name is Alfred!"โดยได้รับมอบหมายเช่น:

const char* a;
a = "Hi My Name is Alfred!";

สลายตัวชี้ไปยังที่อยู่ขององค์ประกอบแรกของตัวอักษรสตริง

หมายถึงaได้รับมอบหมายจากที่อยู่ขององค์ประกอบแรกของตัวอักษรสตริง"Hi My Name is Alfred!"ซึ่งสามารถเก็บไว้ที่ใดก็ได้ในหน่วยความจำขึ้นอยู่กับสภาพแวดล้อมการดำเนินการ

มันไม่ได้อยู่ในความสามารถของโปรแกรมเมอร์ที่เก็บสตริงตัวอักษรอย่างแน่นอน การมอบหมายของคุณเป็นเพียงการมอบหมายและจัดการตัวชี้ตามลำดับอย่างเหมาะสมเท่านั้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.