为什么C ++变量在指针时不需要正确定义?

时间:2015-08-26 18:03:56

标签: c++ arrays pointers char declaration

我对C ++语言完全陌生(特别是指针,经验主要是在PHP中),并希望对以下内容有所解释(我已经尝试过寻找答案)。

两行代码如何在我的程序中完成相同的工作?第二行似乎违背了我所学到的一切。迄今为止对指针的了解。

char disk[3] = "D:";

char* disk = "D:";

我如何初始化指向内存地址以外的任何指针?不仅如此,在第二行我也没有正确地声明阵列 - 但它仍在工作?

3 个答案:

答案 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*实际上是一个错误,因为大多数编译器仍然只是警告它而不是产生错误。