我有我认为应该是一个非常简单的代码片段来编写,尽管由于我不明白的原因我无法编译。
以下简化代码将无法编译:
char buffer[9] = "12345678";
char* pBuffer = &buffer;
编译器 (g++) 抛出以下错误:
error: cannot convert 'char (*)[9]' to 'char*' in initialization
C++ 不完全是我的“本机”语言,但我所看到的任何地方都告诉我这应该可以工作。非常感谢任何想法或建议。
我有我认为应该是一个非常简单的代码片段来编写,尽管由于我不明白的原因我无法编译。
以下简化代码将无法编译:
char buffer[9] = "12345678";
char* pBuffer = &buffer;
编译器 (g++) 抛出以下错误:
error: cannot convert 'char (*)[9]' to 'char*' in initialization
C++ 不完全是我的“本机”语言,但我所看到的任何地方都告诉我这应该可以工作。非常感谢任何想法或建议。
而不是获取数组的地址,而是写
char buffer[9] = "12345678";
char *pBuffer = buffer;
编辑:这一切是什么意思?
T
长度类型的数组n
是内存中的(连续)序列n
T
。
指针是内存地址。
例如,下面的代码
char a[5] = "hello";
char *p = "world";
对应内存中的以下情况:
在您的代码中,您创建了一个数组
char buffer[9] = "12345678";
与创建数组的方式相同char a[5] = "hello"
。您打算创建一个指向char *
数组第一个字符的指针,就像char *p
上面指向数组的第一个字符一样"world"
。
当使用“类型数组”(此处buffer
)类型的表达式时,它总是“衰减”到指向第一个元素的指针,除非
1.
该表达式用作sizeof的操作数(在 中sizeof(buffer)
,buffer
不会衰减为指针)
2.
该表达式用作一元 &的操作数(在 中&buffer
,buffer
不会衰减为指针)
或者
3.
表达式是字符数组的字符串字面量初始化器(在 中char someBuffer[3] = "ab"
,字符串字面量"ab"
是一个数组,不会衰减为指针)。
这在标准的第 6.2.2.1 节中列出:
729 除非它是 sizeof 运算符或一元 & 运算符的操作数,或者是用于初始化数组的字符串字面量,否则“类型数组”类型的表达式将转换为“类型指针”类型的表达式指向数组对象的初始元素并且不是左值。
char *pBuffer
因此,创建指向数组中第一个字符的指针所需要做的就是写
char *pBuffer = buffer;
该声明创建了一个字符char buffer[9] = "12345678";
数组。
这里,是它的第一个元素的地址,而不是数组的地址。 9
buffer
char* pBuffer = buffer;
是一个正确的表达式,因为pBuffer
它是一个指向 char 的指针,并且可以寻址第一个元素。
但是表达式char* pBuffer = &buffer
是错误的,因为pBuffer
无法寻址数组。(代码中的错误,&buffer
数组地址如下所述)
buffer
和之间的区别&buffer
&buffer
表示数组的地址。和的值实际上是相同的,但在语义上两者是不同的。一个是 char 的地址,而另一个是 9 个字符的数组的地址。buffer
&buffer
buffer[9] = "12345678";
+----+----+----+---+---+----+----+----+---+----+
| '1'| '2' |'3'|'4'|'5'| '6'| '7'|'8' | 0 | ...........
+----+----+----+---+---+----+----+----+---+---+----+
201 202 203 204 205 206 207 208 209 210 211
^ ^
| |
(buffer) (buffer + 1)
| |
|-----------------------------------------|--------
|201 | 210
^ ^
| |
(&buffer) (&buffer + 1)
我使用十进制数字而不是十六进制地址
即使 is 的值和isbuffer
的201
值,它们的 含义也不同:&buffer
201
buffer
: 第一个元素的地址——它的类型是char*
.&buffer
: 完整的 char 数组的地址——它的类型是char(*)[9]
. 此外,要观察差异,请添加1
:
buffer + 1
给出202
的是第二个数组元素的地址,'2'
但
&buffer + 1
给出210
的是下一个数组的地址。
在我的系统上,我编写了以下代码:
int main(){
char buffer[9] = "12345678";
char (*pBuffer)[9] = &buffer;
printf("\n %p, %p\n",buffer, buffer+1);
printf("\n %p, %p\n",(&buffer), (&buffer+1));
}
输出如下:
0xbfdc0343, 0xbfdc0344
0xbfdc0343, 0xbfdc034c
[回答]
这就是错误的原因:
错误:无法在初始化中将 'char ( )[9]' 转换为 'char '
您正在尝试将'char (*)[9]'
类型值分配给char*
.
char (*ptr2)[9];
这里ptr2 is pointer to an array of 9 chars
, 而这一次ptr2=&buffer
是一个有效的表达式。如何更正您的代码?
正如内特钱德勒的回答:
char buffer[9] = "12345678";
char* pBuffer = buffer;
或其他方法,
char buffer[9] = "12345678";
char (*pBuffer)[9] = &buffer;
您选择哪种取决于您的需要。
数组衰减为指针,你只需要
char* pBuffer = buffer;
还结帐:std::decay
std::cout << "int[] -> int*; // " << std::boolalpha
<< std::is_same<int *, std::decay<int[]>::type>::value;
输出:
int[] -> int*; // true
错误信息非常清楚;&buffer
是类型char (*)[9]
,即指向具有 9 个元素的 char 数组的指针(是的,数组是完全成熟的类型)。
这与char*
. 但是,数组在需要时会降级为指向第一个元素的指针,所以......
char *pbuffer = buffer;
数组名表示它的基地址,所以如果只写缓冲区,则表示缓冲区[0]的地址。如果你使用 &buffer,你需要在 char** 中而不是在 char * 中。
所以,
char* pBuffer = buffer;
按照建议是正确的。
因为编译器无法将 char( )[] 隐式转换为 char。所以你需要显式类型转换
char buffer[9] = "12345678";
char* pBuffer = (char*)&buffer;