关于 char * [length] 赋值的问题

Question about char * [length] assignment

此代码如何工作?

#include <stdio.h>
#include <string.h>

int main()
{
#define NAME_LEN 10

        char name[NAME_LEN+1];                          // line 8
        strcpy(name,"Hi");                              // line 9
        char (* name_ptr)[NAME_LEN +1] = & name;        // line 10

        printf("%s=%s\n%s=%s\n",                        // line 12
                "name",name,                            // line 13
                "name_ptr",name_ptr                     // line 14
        );
}

第 10 行之前一切都是例行公事。对我来说,第 10 行混合在一起声明 char *char [length],所以我希望有一个 10 char * 的数组(显然,编译器不同意,因为这有效)。当我用 -Wall 编译它时,我得到以下信息:

$ cc -g -Wall a.C
a.C: In function ‘int main()’:
a.C:16:2: warning: format ‘%s’ expects argument of type ‘char*’, but argument 5 has type ‘char (*)[11]’ [-Wformat=]
  );

我错过了什么?

char (* name_ptr)[NAME_LEN +1]

name_ptr 是指向包含 NAME_LEN +1 个元素的 char 数组的指针。所以 this 指针的类型与 char * 不同,即使它们引用相同的对象。

最容易发现和理解的区别是指针运算。

示例:

int main()
{
#define NAME_LEN 10

    char name[NAME_LEN+1];                          // line 8
    strcpy(name,"Hi");                              // line 9
    char (* name_ptr)[NAME_LEN +1] = & name;        // line 10

    printf("name = %p (name + 1) = %p, difference in chars = %td\n", 
            (void *)name, (void *)(name + 1), (char *)(name + 1) - (char *)name);                        // line 12
    printf("name_ptr = %p (name_ptr + 1) = %p, difference in chars = %td\n", 
            (void *)name_ptr, (void *)(name_ptr + 1), (char *)(name_ptr + 1) - (char *)name_ptr);                        // line 12
}

结果:

name = 0x7fff645264b5 (name + 1) = 0x7fff645264b6, difference in chars = 1
name_ptr = 0x7fff645264b5 (name_ptr + 1) = 0x7fff645264c0, difference in chars = 11

如您所见,指向数组的指针将数组的整个大小添加到初始地址。

所以如果你想在 printf 中使用这个指针,你需要取消引用它:

        printf("name_ptr = %s\n",name_ptr[0]);                  
        printf("name_ptr = %s\n",*name_ptr);                  

在 c 中,指针的类型并没有真正改变它指向的内容。

如 0___________ 所述,printf%s 标志预期的 char*(指向字符的指针)与 [=13= 之间的唯一区别](指向11长字符数组的指针)是指针算法。

现在你在第 10 行所做的是让你的 char (*)[11] 指向内存中恰好有 ['h', 'i', '[=15=]'] 的位置。然后在您的 printf 调用中,您告诉它从该位置读取一个字符串。那里确实有一个字符串,以 null 结尾等等。

所以它向你抱怨指针类型,但它仍然按照它所说的去做,因为它在指针指向的地方有它需要的一切。