【问题标题】: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"};

【问题讨论】:

标签: c pointers


【解决方案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" }) 括起来。但是,它可能不是初始化器的列表

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-27
      • 2021-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-21
      相关资源
      最近更新 更多