关于 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] = & name;
。首选:char * name_ptr = &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] 赋值的问题的主要内容,如果未能解决你的问题,请参考以下文章