【问题标题】:incompatible pointer types passing 'char (*)[3]' to parameter of type 'const char *不兼容的指针类型将“char (*)[3]”传递给“const char *”类型的参数
【发布时间】:2021-12-11 20:09:30
【问题描述】:

使用以下代码:

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);
}

我在&amp;temp 收到incompatible pointer types passing 'char (*)[3]' to parameter of type 'const char *。改用temp 可以解决此问题。

我正在尝试理解错误消息。我理解const char * 是一个指针,但我不确定char (*)[3] 指的是什么;特别是(*)。从我可以从修复中推断出来,我假设这是一个指向指针的指针(编辑:指针)。这是正确的吗?

【问题讨论】:

标签: arrays c pointers


【解决方案1】:

&amp;temp整个数组的地址。数组的类型是char [3],所以地址(指针)的类型是指向那个数组的指针,表示为char (*) [3],读作“指向3个数组的指针chars”。

我假设这是一个指向指针的指针。

不,它是指向数组的指针。

【讨论】:

    【解决方案2】:

    &amp;temp 是一个指向数组本身的指针,它确实具有char (*)[3] 类型(它是一个指向三个char 元素的数组的指针)。

    您应该传递一个指向字符串第一个元素的指针,即&amp;temp[0],这就是普通的temp 衰减

    所以:

    strcat(buff, temp);
    

    【讨论】:

      【解决方案3】:

      char (*)[3] 是一个指向大小为 3 的数组的指针。

      temp 最“自然”的形式是char[3] 类型。但是,因为temp 也指向数组的第一个元素(即char),所以允许它“衰减”为char*

      当你取&amp;temp 时,它给出了temp 变量的地址,不是一个地址位于数组中。同样,在其最“自然”的形式中,&amp;temp 的类型为 char (*)[3],因为它是指向 char[3] 的指针。但是请注意,它不再是数组类型(而是指向数组的指针),因此不允许衰减到char**

      strcat(buff, temp); 解决了这个问题,因为 strcat 需要 char*,而不是 char (*)[3]

      【讨论】:

      • 不,char(*)[3]char** 本质上是不同的,前者不能衰减为后者。 char** 是指向 char* 的指针,它可能是 char* 的数组,但它不是长度为 3 的 char 数组。
      • char *[]char (*)[]char ** 完全不同
      • 比较:char** pp; char(*pa)[3]; 你得到的sizeof(*pp) 等于指针的大小(通常为 4 或 8,取决于系统),而 sizeof(*pa) 等于 3!
      • 你是对的,看看我的编辑。 @Aconcagua 我不确定这是一个有效的例子,因为您取消引用 papp,所以实际上您只是比较 char*char[3],而不是 char**char(*)[3]
      • 扩展@0_______ 的评论:请注意,char*[] 可以衰减为 char**...
      【解决方案4】:

      数组衰减为指针。

      char temp[3];
      
      • temp 衰减为指向数组第一个元素的 char (char *) 的指针
      • &amp;temp 衰减为指向数组开头的 3 个字符 (char (*)[3]) 的指针
      • &amp;temp[n] 衰减为指向数组的第 n 个元素的 char (char *) 的指针

      【讨论】:

      • Address-of 运算符直接返回一个指针,decay 不是这个上下文的正确词,是吗?
      • 确实,&amp;sizeof 运算符是数组衰减规则的例外。
      【解决方案5】:

      函数strcat声明如下

      char *strcat(char * restrict s1, const char * restrict s2);
      

      如您所见,它的两个参数都需要char *const char * 类型的表达式。

      在这个函数的调用中

      strcat(buff, &temp);
      

      第一个参数表达式确实具有 char * 类型,因为数组指示符 buff 的隐式转换声明为

      char buff[KEYSIZE*2 + 1] = {0};  
      

      指向第一个元素的指针。

      虽然第二个参数表达式的类型为 char ( * )[3],因为您将运算符 &amp; 的地址用于数组 temp

      &temp
      

      您还需要使用数组指示符temp 作为参数。在这种情况下,它将被隐式转换为指向其第一个元素的指针,其方式与数组 buff 类似。

      strcat(buff, temp);
      

      请注意,最初数组 random 应声明为具有元素类型 unsigned char

      unsigned char randnum[KEYSIZE + 1];
      

      此外,由于数组并非旨在包含字符串,因此它也可以声明为

      unsigned char randnum[KEYSIZE];
      

      char randnum[KEYSIZE + 1];

      【讨论】:

        【解决方案6】:

        strcat 函数声明为 (C17 7.24.3.1):

        char *strcat(char * restrict s1,
                     const char * restrict s2);
        

        本次讨论的重要部分是该函数需要char* 用于两个参数。虽然我们可以注意到 char* 可以分配给 const char*,但反过来不行。

        如果我们查看正确的用法strcat(buff, temp);,那么该表达式中的bufftemp 都是数组。但在大多数情况下,当在表达式中使用数组时,它会“衰减”为指向其第一个元素的指针,在这种情况下,它会变成 char*

        这个“衰变”正式定义为(C17 6.3.2.1):

        除非它是sizeof 运算符的操作数,或一元&amp; 运算符,或者是用于初始化数组的字符串文字,否则表达式的类型为''array of type em>'' 被转换为类型为 ''pointer to type'' 的表达式,它指向数组对象的初始元素并且不是左值。

        然而当您输入&amp;temp 时,您会偶然发现上述“数组衰减”规则的例外之一,即与一元&amp; 一起使用时。

        因此,我们最终得到的不是char*,而是“char [3] 的地址”。必须用指向数组时使用的特殊指针类型char (*)[3] 来表示,称为“指向数组的指针”或“数组指针”。

        C 对隐式指针转换有非常严格的规则 - 它不会接受将 char(*)[3] 传递给预期为 const char* 的参数 - 它们是不兼容的指针类型 - 它不是有效的赋值形式。

        当您了解所有这些后,编译器错误实际上是不言自明的。

        【讨论】:

          猜你喜欢
          • 2015-03-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-16
          • 2016-05-19
          • 2021-06-29
          • 2020-01-20
          相关资源
          最近更新 更多