使用以下代码:
char randnum[KEYSIZE + 1];
char temp[3];
char buff[KEYSIZE*2 + 1] = {0};
for (j = 0; i < KEYSIZE; i++) {
randnum[i] = rand()%256;
snprintf(temp, 3, "%.2x", (unsigned char)randnum[i]);
strcat(buff, &temp);
}
我在&temp
拿到incompatible pointer types passing 'char (*)[3]' to parameter of type 'const char *
。这是通过使用temp
来修复的。
我正在努力理解错误信息。我理解const char *
是一个指针,但我不确定char (*)[3]
指的是什么;特别是CCD_ 6。根据我从修复中推断出的内容,我假设这是一个指向指针的指针(EDIT:pointer)。这是正确的吗?
&temp
是整个数组的地址。该数组的类型为char [3]
,因此地址(指针)的类型是指向该数组的指针,表示为char (*) [3]
,将其读取为"0";指向3个char
s的阵列的指针";。
我假设这是一个指向指针的指针
不,它是指向数组的指针。
&temp
是指向数组本身的指针,它确实具有类型char (*)[3]
(它是指向三个char
元素的数组的指针)。
您应该将指针传递到字符串的第一个元素,即&temp[0]
,这就是普通temp
衰减的结果。
因此:
strcat(buff, temp);
函数strcat
以以下方式声明
char *strcat(char * restrict s1, const char * restrict s2);
正如您所看到的,它的两个参数都需要类型为char *
或const char *
的表达式。
在函数的调用中
strcat(buff, &temp);
由于像一样声明的数组指示符buff
的隐式转换,第一个自变量表达式确实具有类型char *
char buff[KEYSIZE*2 + 1] = {0};
指向指向其第一个元素的指针。
而第二个参数表达式的类型为char ( * )[3]
,因为您将运算符&
的地址用于数组temp
&temp
您还需要使用数组指示符temp
作为参数。在这种情况下,它将以与数组buff
类似的方式隐式转换为指向其第一个元素的指针。
strcat(buff, temp);
请注意,最初应该将数组random
声明为具有元素类型unsigned char
。
unsigned char randnum[KEYSIZE + 1];
此外,由于数组没有被设计为包含字符串,因此它也可以像一样被声明
unsigned char randnum[KEYSIZE];
char randnum[KEYSIZE+1];
数组衰减为指针。
char temp[3];
temp
衰减为指向引用数组第一个元素的字符的指针(char *
)&temp
衰减为指向引用数组开头的3个字符数组(char (*)[3]
)的指针&temp[n]
衰减为指向引用数组第n个元素的字符的指针(char *
)
strcat
函数声明为(C17 7.24.3.1):
char *strcat(char * restrict s1,
const char * restrict s2);
对于本讨论而言,重要的部分是函数对两个参数都期望char*
。尽管我们可以注意到char*
可以分配给const char*
,但不能反过来。
如果我们看看正确的用法strcat(buff, temp);
,那么该表达式中的buff
和temp
都是数组。但在大多数情况下,当在表达式中使用数组时;衰变";在这种情况下,它变为char*
。
正式地说;衰变;定义为(C17 6.3.2.1):
除非它是
sizeof
运算符、一元&
运算符的操作数,或者是用于初始化数组的字符串文字,否则类型为">类型的数组"的表达式将转换为类型为"指向型型"的表达式,该表达式指向数组对象的初始元素,而不是左值。
然而当您键入&temp
时,您会偶然发现上面提到的"异常之一;阵列衰减";规则,即当与一元&
一起使用时。
因此,我们最终得到的不是CCD_ 46;CCD_ 47"的地址;。它必须用指向数组时使用的特殊指针类型char (*)[3]
来表示,称为";指向数组的指针";或";数组指针";。
C对隐式指针转换有非常严格的规则——它不会接受将char(*)[3]
传递给预期为const char*
的参数——它们是不兼容的指针类型——这不是一种有效的赋值形式。
当您知道所有这些之后,编译器错误实际上是不言自明的。
char (*)[3]
是指向大小为3的数组的指针。
CCD_;天然的";形式为CCD_ 53型。然而,因为temp
也指向数组的第一个元素(它是char
),所以允许"0";衰变;转换为CCD_ 56。
当您取&temp
时,它给出了temp
变量的地址,而不是地址位于数组中。再次,在其最";天然的";形式,&temp
是(*)
0类型,因为它是指向char[3]
的指针。但是,请注意,它不再是数组类型(而是指向数组的指针),因此不允许衰减为char**
。
strcat(buff, temp);
修复了这个问题,因为strcat
想要的是char*
,而不是char (*)[3]
。