Jam*_*ole 3 c++ arrays pointers declaration char
我对C++语言完全陌生(特别是指针,经验主要是在PHP中)并且希望对以下内容有所解释(我已经尝试过寻找答案).
两行代码如何能够在我的程序中完成相同的工作?第二行似乎违背了我迄今为止所学到的和关于指针所理解的一切.
char disk[3] = "D:";
char* disk = "D:";
我怎么能初始化指向内存地址以外的任何指针?不仅如此,在第二行我也没有正确地声明阵列 - 但它仍在工作?
在C和C++中初始化数组的常用方法是:
int a[3] = { 0, 1, 2 };
Run Code Online (Sandbox Code Playgroud)
旁白:您可以选择省略数组绑定并从初始化列表中推导出它,或者具有比初始化器更大的边界:
int aa[] = { 0, 1, 2 }; // another array of three ints
int aaa[5] = { 0, 1, 2 }; // equivalent to { 0, 1, 2, 0, 0}
对于字符数组,有一个特殊规则允许从字符串文字初始化数组,数组的每个元素都是从字符串文字中的相应字符初始化的.
您的第一个示例使用字符串文字,"D:"因此数组的每个元素都将初始化为该字符串中的字符,相当于:
char disk[3] = { 'D', ':', '\0' };
Run Code Online (Sandbox Code Playgroud)
(第三个字符是空终止符,它隐式存在于所有字符串文字中).
旁白:在这里你也可以选择省略数组绑定并从字符串文字推导出它,或者具有比字符串长度更大的边界:char dd[] = "D:"; // another array of three chars char ddd[5] = "D:"; // equivalent to { 'D', ':', '\0', '\0', '\0'}就像aaa上面的例子一样,ddd字符串中没有相应字符的额外元素将被零初始化.
您的第二个示例有效,因为字符串文字"D:"将由编译器输出并存储在可执行文件中的某个位置,作为三个字符的数组.运行可执行文件时,包含该数组的段(以及其他常量)将映射到进程的地址空间.因此,char*然后将指针初始化为指向该数组的位置,无论发生在何处.从概念上讲,它类似于:
const char __some_array_created_by_the_compiler[3] = "D:";
const char* disk = __some_array_created_by_the_compiler;
Run Code Online (Sandbox Code Playgroud)
由于历史原因(大多数const在C的早期并不存在),使用非const char*指向该数组是合法的,即使该数组实际上是只读的,因此C和第一个C++标准允许您使用非const char*指针指向字符串文字,即使它引用的数组实际上是const:
const char __some_array_created_by_the_compiler[3] = "D:";
char* disk = (char*)__some_array_created_by_the_compiler;
Run Code Online (Sandbox Code Playgroud)
这意味着尽管出现了两个例子并不完全相同,因为这只允许第一个:
disk[0] = 'C';
Run Code Online (Sandbox Code Playgroud)
对于第一个没有问题的例子,它改变了数组的第一个元素.
对于第二个示例,它可能会编译,但它会导致未定义的行为,因为它实际上正在做的是修改__some_array_created_by_the_compiler只读的第一个元素.在实践中,可能发生的是该过程将崩溃,因为尝试写入只读内存页面将引发分段错误.
重要的是要理解C++中有很多东西(甚至更多在C语言中),编译器很乐意编译它们,但是当代码执行时会导致非常糟糕的事情发生.
char disk[3] = "D:";
Run Code Online (Sandbox Code Playgroud)
被视为
char disk[3] = {'D',':','\0'};
Run Code Online (Sandbox Code Playgroud)
在C++ 11及以上版本中
char* disk = "D:";
Run Code Online (Sandbox Code Playgroud)
是一个错误,因为字符串文字是类型的const char[],不能分配给char *.你可以将它分配给一个const char *.
字符串文字实际上是只读的,以零结尾的字符数组,并且使用字符串文字为您提供指向数组中第一个字符的指针.
所以在第二个例子中
char* disk = "D:";
Run Code Online (Sandbox Code Playgroud)
初始化disk为指向三个字符数组的第一个字符.
在我上面的第一段中注意到,我说字符串文字是只读数组,这意味着有一个简单的char*指向这个数组可能会让你认为可以修改这个数组当它不是(试图修改字符串文字的线索)到未定义行为).这是const char*通常使用的原因:
const char* disk = "D:";
Run Code Online (Sandbox Code Playgroud)
从C++ 11开始,不使用a实际上是一个错误const char*,通过大多数编译器仍然只是警告它而不是产生错误.