我对C ++语言完全陌生(特别是指针,经验主要是在PHP中),并希望对以下内容有所解释(我已经尝试过寻找答案)。
两行代码如何在我的程序中完成相同的工作?第二行似乎违背了我所学到的一切。迄今为止对指针的了解。
char disk[3] = "D:";
char* disk = "D:";
我如何初始化指向内存地址以外的任何指针?不仅如此,在第二行我也没有正确地声明阵列 - 但它仍在工作?
答案 0 :(得分:7)
在C和C ++中初始化数组的常用方法是:
int a[3] = { 0, 1, 2 };
旁白:您可以选择省略数组绑定并从初始化列表中推导出它,或者具有比初始化器更大的界限: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' };
(第三个字符是null terminator,它隐含存在于所有字符串文字中。)
旁白:在这里你也可以选择省略数组绑定并从字符串文字推导出它,或者具有比字符串长度更大的边界: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;
由于历史原因(大多数情况下,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;
这意味着尽管出现了两个例子并不完全相同,因为这只允许第一个:
disk[0] = 'C';
对于第一个没有问题的例子,它改变了数组的第一个元素。
对于第二个例子,它可能会编译,但它会产生undefined behaviour,因为它实际上正在做的是修改__some_array_created_by_the_compiler
的只读的第一个元素。在实践中,可能会发生的是该过程将崩溃,因为尝试写入只读内存页面会引发分段错误。
重要的是要理解C ++中有很多东西(在C语言中甚至更多),编译器很乐意编译它们,但是在执行代码时会导致非常糟糕的事情发生。
答案 1 :(得分:5)
char disk[3] = "D:";
被视为
char disk[3] = {'D',':','\0'};
在C ++ 11及以上版本中
char* disk = "D:";
作为字符串文字的错误是const char[]
类型,并且无法分配给char *
。您可以将其分配给const char *
。
答案 2 :(得分:5)
字符串文字实际上是只读的,以零结尾的字符数组,并且使用字符串文字为您提供指向数组中第一个字符的指针。
所以在第二个例子中
char* disk = "D:";
初始化disk
以指向三个字符数组的第一个字符。
在我上面的第一段中注意,我说字符串文字是只读数组,这意味着指向这个数组的普通char*
可能会让你认为它&# 39;如果没有(修改字符串文字导致未定义的行为),可以修改此数组。这就是const char*
通常使用的原因:
const char* disk = "D:";
自从C ++ 11以来,不使用const char*
实际上是一个错误,因为大多数编译器仍然只是警告它而不是产生错误。