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

Posted

技术标签:

【中文标题】关于 char * [length] 赋值的问题【英文标题】:Question about char * [length] assignment 【发布时间】:2022-01-06 18:09:31 【问题描述】:

这段代码是如何工作的?

#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=]
  );

我错过了什么?

【问题讨论】:

@paulsm4 肯定编译器不认为这是一个函数。 在 C 中声明指向数组的指针似乎很棘手且不常见。您可以使用普通的 char * 指针:char * name_ptr = name; 【参考方案1】:
char (* name_ptr)[NAME_LEN +1]

name_ptr 是指向 char 数组的指针,该数组由 NAME_LEN +1 元素组成。所以这个指针的类型和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);                  

【讨论】:

你绝对应该反对这样的语法:char (* name_ptr)[NAME_LEN +1] = &amp; name;。首选:char * name_ptr = &amp;name[0] ;(如果这是 OP 的实际意图)。清楚地区分类型声明(左侧)和赋值(右侧)。 @paulsm4 抱歉,您根本不理解这段代码。此分配是 100% 正确的,因为它将对 array 的引用分配给 pointer to array。这个答案解释了它并展示了如何使用这种指针。【参考方案2】:

在 c 中,指针的类型并不会真正改变它所指向的内容。

正如 0___________ 所提到的,printf%s 标志所期望的 char*(指向字符的指针)和 char (*)[11](指向 11 长字符数组的指针)之间的唯一区别是指针算术.

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

所以它会向你抱怨指针类型,但它仍然按照它的指示行事,因为它在指针指向的地方拥有它所需要的一切。

【讨论】:

以上是关于关于 char * [length] 赋值的问题的主要内容,如果未能解决你的问题,请参考以下文章

java char String中涉及到的length字符长度概念的研究

JavaScript 关于this的赋值问题

关于C++中string类型变量的赋值

jQuery $.get获取值后赋值

关于char * 和 char [] 的一点理解

关于unsigned char 型数据转换成十进制或者16进制的问题