为啥 C 双星号不能用于创建二维数组?
Posted
技术标签:
【中文标题】为啥 C 双星号不能用于创建二维数组?【英文标题】:Why doesn't the C double asterisk work for creating a 2D array?为什么 C 双星号不能用于创建二维数组? 【发布时间】:2021-11-05 06:09:49 【问题描述】:为什么会这样:
char *name = "steven";
但这不是:
char **names = "steven", "randy", "ben";
或者,为什么会这样:
char *names[] = "steven", "randy", "ben";
但是,这又不是:
char **names = "steven", "randy", "ben";
【问题讨论】:
TLDR:因为char **names
不引用二维数组,不管你被告知什么。见Correctly allocating multi-dimensional arrays
这能回答你的问题吗? Double pointer vs array of pointers(**array vs *array[])
谢谢,是的,这两个链接都很有帮助。所以当你有 char
那么当你有 char *names[] = "bob", ... 时,names 是一个指针吗?
不,[]
表示names
是一个数组,char *
表示该数组包含指向char
的指针
【参考方案1】:
char **p
不是二维数组,它是指向字符指针的指针。但是,您可以有更多的指针和更多的字符跟随,类似于一种 2D 字符结构的模型。
C 编译器将 "steven"
解释为一维字符数组,因为大括号是可选的(标准章节 6.7.9 第 14 段)。
正如您所尝试的,您可以通过char *p[]
声明一个指向字符的指针数组。
但是如果你想要那个指针(指向字符的指针),你需要告诉你的编译器。数组的地址可以赋值给指针。
char **p = (char *[]) "steven", "randy", "ben", ;
附加说明:由于字符串文字是不可变的,因此您最好为字符添加const
。由于这些未命名的字符串字面量的地址也是常量,因此您可以提供另一个地址。
const char * const *p = (const char * const []) "steven", "randy", "ben", ;
【讨论】:
谢谢。我是否正确地说 (char *[]) "steven", "randy", "ben", 是类型转换? 嗯,它是一个复合字面量,参见第 6.5.2.5 章。该标准将其与演员表区分开来。 这与演员阵容大不相同。它创建(分配内存)一个对象;该对象具有定义的生命周期,您必须注意这一点。【参考方案2】:我也想知道,如果我能以最简单的方式回答你呢。
你为什么感到困惑?
一个指向整数的简单指针,例如分配8 个单元,其作用方式与一个维数为8 个单元的数组相同。 您看不到的唯一区别是分配了 8 个单元的指针位于称为 HEAP 的内存部分,而 int tab[8] 类型的变量在 STACK 上分配。 确实,由于单元格在内存中是相互链接的,所以很容易想象,发送第一个单元格地址的指针和数组是一回事。
为什么它在其他情况下不起作用
但是,当想到将 (** 和 [][]) 关联起来时 我们以 int ** 为例;
int **tab;
tab = malloc(sizeof(int *) * 4);
//secure malloc do not forget
for (int i = 0; i < 4; i++)
tab[i] = malloc(sizeof(int) * 3);
//secure malloc do not forget
还有一个
int[4][3];
你有问题。 想象一下,double 数组类型在内存中跟随其自身,因为这正是数组的原理。
虽然双指针首先分配了 4 个 int * 类型的单元(它们在内存中相互跟随),然后这 4 个单元的每个指针都指向一个由 3 个相互跟随的 int 组成的内存区域。但整件事在记忆中并没有互相跟随!
您可能感兴趣的方式
您可以做的一件事是创建一个int ptr(*)[3];
它可以指向一个大小为 3 的数组的第一个元素,例如数组 [4][3]
的地址。
【讨论】:
【参考方案3】:标量对象的初始化程序不能包含多个项目。
6.7.9 初始化 ...约束 2 任何初始化程序都不应尝试为不包含在实体中的对象提供值 正在初始化。 ... 11 标量的初始值设定项应该是一个表达式,可选地用大括号括起来。这 对象的初始值是表达式的初始值(转换后);同类型 适用于简单赋值的约束和转换,采用标量的类型 成为其声明类型的非限定版本C 2011 Online Draft
char **names
声明了一个单一的标量对象,而不是一个数组,因此它的任何初始化程序必须只包含一个项目。该初始值设定项可以是单个字符串 ("steven"
),可选择用大括号 ( "steven"
) 括起来。但是,它可能不是初始化器的列表。
【讨论】:
以上是关于为啥 C 双星号不能用于创建二维数组?的主要内容,如果未能解决你的问题,请参考以下文章