ความแตกต่างระหว่างอะไร
char* name
ซึ่งชี้ไปที่ตัวอักษรสตริงคงที่และ
const char* name
ความแตกต่างระหว่างอะไร
char* name
ซึ่งชี้ไปที่ตัวอักษรสตริงคงที่และ
const char* name
คำตอบ:
char*
เป็นตัวชี้ที่เปลี่ยนแปลงไม่ได้ไปที่ไม่แน่นอนตัวอักษร / สตริง
const char*
เป็นไม่แน่นอนชี้ไปยังไม่เปลี่ยนรูปตัวอักษร / สตริง คุณไม่สามารถเปลี่ยนเนื้อหาของสถานที่ที่ตัวชี้นี้ชี้ไป นอกจากนี้คอมไพเลอร์จะต้องให้ข้อความแสดงข้อผิดพลาดเมื่อคุณพยายามทำ ด้วยเหตุผลเดียวกันการแปลงจากconst char *
เป็นchar*
เลิก
char* const
เป็นตัวชี้ที่ไม่เปลี่ยนรูป (ไม่สามารถชี้ไปยังตำแหน่งอื่นได้) แต่เนื้อหาของตำแหน่งที่จุดนั้นเปลี่ยนแปลงได้ได้
const char* const
เป็นไม่เปลี่ยนรูปชี้ไปยังไม่เปลี่ยนรูปตัวอักษร / สตริง
char const *
char *
ทำให้เกิดการแบ่งเซ็กเมนต์ผิดพลาดขณะทำงานหรือไม่
const
ถ้าฉันต้องการให้คอมไพเลอร์ให้ข้อผิดพลาดถ้าฉันลืมและเปลี่ยนแปลงข้อมูลโดยไม่ได้ตั้งใจใช่ไหม
char *name
คุณสามารถเปลี่ยนถ่านที่ name
จุดใดก็ได้และถ่านที่มันชี้ไป
const char* name
คุณสามารถเปลี่ยนถ่านให้เป็นname
จุดใด แต่คุณไม่สามารถแก้ไขถ่านที่ชี้ไปได้
การแก้ไข:คุณสามารถเปลี่ยนชี้ แต่ไม่ได้ถ่านที่name
จุดที่จะ ( https://msdn.microsoft.com/en-us/library/vstudio/whkd4k6a(v=vs.100).aspxดู "ตัวอย่าง" ) ในกรณีนี้ตัวconst
ระบุจะใช้กับchar
ไม่ใช่เครื่องหมายดอกจัน
ตามไปที่หน้า MSDN และhttp://en.cppreference.com/w/cpp/language/declarationsที่const
ก่อนที่จะ*
เป็นส่วนหนึ่งของลำดับ decl-ระบุในขณะที่const
หลังจากที่*
เป็นส่วนหนึ่งของ declarator
ลำดับประกาศระบุสามารถตาม declarators หลายซึ่งเป็นเหตุผลที่const char * c1, c2
ประกาศc1
เป็นconst char *
และเป็นc2
const char
แก้ไข:
จากความคิดเห็นคำถามของคุณดูเหมือนจะถามเกี่ยวกับความแตกต่างระหว่างการประกาศทั้งสองเมื่อตัวชี้ชี้ไปที่ตัวอักษรสตริง
ในกรณีดังกล่าวคุณไม่ควรแก้ไขอักขระที่เป็นname
จุดซึ่งอาจส่งผลให้พฤติกรรมที่ไม่ได้กำหนดพฤติกรรมที่ไม่ได้กำหนดสตริงตัวอักษรอาจถูกจัดสรรในขอบเขตหน่วยความจำแบบอ่านอย่างเดียว (กำหนดการใช้งาน) และโปรแกรมผู้ใช้ไม่ควรแก้ไขใน ความพยายามใด ๆ ในการทำเช่นนั้นจะส่งผลในพฤติกรรมที่ไม่ได้กำหนด
ดังนั้นความแตกต่างเพียงอย่างเดียวในกรณีนั้น (ของการใช้งานที่มีตัวอักษรสตริง) คือการประกาศครั้งที่สองให้ข้อได้เปรียบเล็กน้อยกับคุณ คอมไพเลอร์มักจะให้คำเตือนคุณในกรณีที่คุณพยายามแก้ไขสตริงตัวอักษรในกรณีที่สอง
#include <string.h>
int main()
{
char *str1 = "string Literal";
const char *str2 = "string Literal";
char source[] = "Sample string";
strcpy(str1,source); //No warning or error, just Undefined Behavior
strcpy(str2,source); //Compiler issues a warning
return 0;
}
เอาท์พุท:
cc1: คำเตือนที่ถือว่าเป็นข้อผิดพลาด
prog.c: ในฟังก์ชัน 'main':
prog.c: 9: ข้อผิดพลาด: ผ่านการโต้แย้ง 1 ของ 'strcpy' ยกเลิกตัวระบุจากประเภทเป้าหมายของตัวชี้
สังเกตว่าคอมไพเลอร์เตือนสำหรับกรณีที่สอง แต่ไม่ใช่สำหรับกรณีแรก
name
จุดในทั้งสองกรณีมันอาจส่งผลให้เกิด UB
char mystring[101] = "My sample string";
const char * constcharp = mystring; // (1)
char const * charconstp = mystring; // (2) the same as (1)
char * const charpconst = mystring; // (3)
constcharp++; // ok
charconstp++; // ok
charpconst++; // compile error
constcharp[3] = '\0'; // compile error
charconstp[3] = '\0'; // compile error
charpconst[3] = '\0'; // ok
// String literals
char * lcharp = "My string literal";
const char * lconstcharp = "My string literal";
lcharp[0] = 'X'; // Segmentation fault (crash) during run-time
lconstcharp[0] = 'X'; // compile error
// *not* a string literal
const char astr[101] = "My mutable string";
astr[0] = 'X'; // compile error
((char*)astr)[0] = 'X'; // ok
char *
ค่าจะทำให้การแบ่งกลุ่มเกิดข้อผิดพลาดเนื่องจากเรากำลังพยายามแก้ไขสตริงตัวอักษร (ซึ่งมีอยู่ในหน่วยความจำแบบอ่านอย่างเดียว)
ในกรณีที่ทั้งคุณสามารถแก้ไขตัวอักษรสตริงโดยไม่คำนึงว่าตัวชี้ไปยังตัวอักษรสตริงที่ถูกประกาศเป็นหรือchar *
const char *
อย่างไรก็ตามความแตกต่างคือถ้าตัวชี้เป็นconst char *
คอมไพเลอร์จะต้องให้การวินิจฉัยถ้าคุณพยายามที่จะแก้ไขค่าชี้ไปที่ แต่ถ้าตัวชี้เป็นchar *
แล้วมันไม่ได้
extern ... name
*name = 'X';
ใน 'ระบบปฏิบัติการที่เหมาะสม' ซึ่งอาจล้มเหลว แต่สำหรับระบบฝังตัวฉันคาดหวังให้ทำบางสิ่งบางอย่างเฉพาะแพลตฟอร์ม / คอมไพเลอร์
กรณีที่ 1:
char *str = "Hello";
str[0] = 'M' //Warning may be issued by compiler, and will cause segmentation fault upon running the programme
ด้านบนตั้งค่า str to ชี้ไปที่ค่าตัวอักษร "Hello" ซึ่งเป็นรหัสตายตัวในอิมเมจไบนารีของโปรแกรมซึ่งถูกตั้งค่าสถานะเป็นหน่วยความจำแบบอ่านอย่างเดียวหมายความว่าการเปลี่ยนแปลงใด ๆ ในตัวอักษรสตริงนี้ผิดกฎหมาย
กรณีที่ 2:
const char *str = "Hello";
str[0] = 'M' //Compile time error
กรณีที่ 3:
char str[] = "Hello";
str[0] = 'M'; // legal and change the str = "Mello".
ครั้งแรกที่คุณสามารถเปลี่ยนแปลงได้จริงถ้าคุณต้องการที่สองคุณไม่สามารถ อ่านเกี่ยวกับconst
ความถูกต้อง (มีคำแนะนำดีๆเกี่ยวกับความแตกต่าง) นอกจากนี้ยังมีchar const * name
ที่ที่คุณไม่สามารถสั่งการได้
คำถามคือสิ่งที่แตกต่างกัน
char *name
ซึ่งชี้ไปที่ตัวอักษรสตริงคงที่และ
const char *cname
คือให้
char *name = "foo";
และ
const char *cname = "foo";
มีความแตกต่างไม่มากระหว่าง 2 และทั้งคู่ที่สามารถมองเห็นได้อย่างถูกต้อง เนื่องจากรหัส C ที่สืบทอดมานานทำให้ตัวอักษรสตริงมีประเภทchar[]
ไม่ใช่const char[]
และมีรหัสเก่าจำนวนมากที่ยอมรับเช่นเดียวกันchar *
แทนconst char *
แม้ว่าจะไม่ได้แก้ไขอาร์กิวเมนต์
ความแตกต่างที่สำคัญของ 2 โดยทั่วไปก็คือว่า*cname
หรือcname[n]
จะมีการประเมินเพื่อ lvalues ชนิดconst char
ในขณะที่*name
หรือname[n]
จะมีการประเมินเพื่อ lvalues ประเภทchar
ซึ่งเป็นlvalues แก้ไขได้ คอมไพเลอร์ที่สอดคล้องจะต้องสร้างข้อความการวินิจฉัยหากเป้าหมายของการมอบหมายไม่ใช่ lvalue ที่แก้ไขได้ ; ไม่จำเป็นต้องมีคำเตือนใด ๆ เกี่ยวกับการกำหนดค่า lvalues ประเภทchar
:
name[0] = 'x'; // no diagnostics *needed*
cname[0] = 'x'; // a conforming compiler *must* produce a diagnostics message
คอมไพเลอร์ไม่จำเป็นต้องหยุดการคอมไพล์ในทั้งสองกรณี มันก็เพียงพอที่จะผลิตคำเตือนcname[0]
สำหรับการมอบหมายให้ โปรแกรมผลลัพธ์ไม่ได้เป็นโปรแกรมที่ถูกต้อง พฤติกรรมของโครงสร้างจะไม่ได้กำหนด มันอาจผิดพลาดหรือแย่กว่านั้นก็อาจไม่ผิดพลาดและอาจเปลี่ยนสตริงตัวอักษรในหน่วยความจำ
ที่จริงแล้วchar* name
ไม่ใช่ตัวชี้ไปยังค่าคงที่ แต่เป็นตัวชี้ไปยังตัวแปร คุณอาจพูดถึงคำถามอื่นนี้