初始化一个指向指针的数组

4

这个例子很好用:

static char *daytab[] = {
    "hello",
    "world"
};

这个不行:
static char *daytab[] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

我认为第一个例子创建了一个数组,其中填充了指向两个字符串字面值(它们本身就是数组)的指针。在我看来,第二个例子应该是相同的 - 创建一个数组并用指向两个字符数组的指针填充它。
有人能解释一下为什么第二个例子是错误的吗?
附言:你可能可以这样写(没有测试过):
static char a[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static char b[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static char *daytab[] = {
    a,
    b
};

但这看起来太麻烦了 :).

4个答案,但我只看到一个?怎么回事? - Ree
我前几天也遇到了这个问题。似乎Stack Overflow需要一段时间才能完全处理已删除的答案。它会很快恢复到正确的计数。 - RBerteig
6个回答

4

This:

{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}

这只是一个数组初始化器,它本身并不创建数组。在第一个例子中,当您将字符串字面值分配给指针时,确实在静态存储区域(对您隐藏)中创建了这些字符串,然后只是将指向它们的指针赋值给它们。

因此,基本上没有办法使用数组初始化器来初始化char*。您需要创建一个实际的数组,并将这些数字分配给它。您需要做类似以下的事情:

char a[][] = { {32, 30, 0}, {34, 32, 33, 0} }; // illegal

但那是非法的。

你需要单独构建数组,并将它们分配到一个数组中,就像你上一个例子那样。


不行。如果您指定第二个维度,第一个维度可以留空[],因此您的示例/char a [][12] = {"hello","world"}; /是合法的。 - Paul Beckingham
第一个例子是完全合法的 - 我不需要创建显式指向字符串的指针。然而,问题在于第二个例子。 - Ree
为什么我在第一个例子中可以将它们都留空,但在第二个例子中却不行?字符串字面量是数组,在第二个例子中我也有数组? - Ree
现在你已经编辑了你的答案,事情现在更加清晰明了。谢谢。 - Ree

3

嗯,这个帖子已经有点老了,不过我也遇到了同样的问题,并找到了一种初始化指向数组的指针数组的方法,就像这样:

#include <iostream>
using namespace std;

int *a[] = {
  (int[]) { 0 } ,
  (int[]) { 1 , 2 } ,
  (int[]) { 3 , 4 , 5 } ,
  (int[]) { 6 , 7 , 8 , 9 }
};

main()
{
  cout
  << a[0][0] << endl
  << a[1][0] << " " << a[1][1] << endl
  << a[2][0] << " " << a[2][1] << " " << a[2][2] << endl
  << a[3][0] << " " << a[3][1] << " " << a[3][2] << " " << a[3][3] << endl;
}

我使用gnu g++编译后,得到了输出结果。

0
1 2
3 4 5
6 7 8 9

使用Intel ICPC进行编译

0
1 1
40896 32767 -961756724
0 32767 4198878 0

因此,语法原则上是正确的,只是英特尔编译器不正确地支持它,可能是由于这种风格缺乏常见用法。


--- 编辑 ---

这里还有一个 C 版本(按需求提供):

#include <stdio.h>

int *a[] = { 
  (int[]) { 0 } , 
  (int[]) { 1 , 2 } , 
  (int[]) { 3 , 4 , 5 } , 
  (int[]) { 6 , 7 , 8 , 9 } 
};

int main()
{
  printf( "%d\n" , a[0][0] );
  printf( "%d %d\n" , a[1][0] , a[1][1] );
  printf( "%d %d %d\n" , a[2][0] , a[2][1] , a[2][2] );
  printf( "%d %d %d %d\n" , a[3][0] , a[3][1] , a[3][2] , a[3][3] );
}

我用gcc和clang进行了测试,输出了正确的结果。顺便说一句,英特尔编译器的错误输出是编译器的一个bug。

好的,但问题严格与C相关(请参见标签),所以如果您的示例不包含C++代码会更好。 - Ree
这并不完全相同。我正在寻找相同的问题,但我需要数组有名称。 - Marco van de Voort

3

尝试:

static char daytab[][13] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

这些不是char*。它们也不是char类型。你可能需要:

static int daytab[][13] ...

那么这将使得主数组的每个元素大小为13。如果我想要指向不同大小的数组的指针呢?至于char - char可用于小整数值,因此在这里没有问题。 - Ree
如果您指定了第二个维度,则第一个维度将通过初始化列表定义。 - Paul Beckingham
抱歉,您的回答与我的初始评论无关。如果我按照您的说法去做,“那将使得主数组的每个元素大小为13”。我想要的是初始化一个指向不同大小数组的指针数组。 - Ree
你不能为任意大小的维度分配值 - 这需要使用Perl及其类似语言。我只是向你展示了解决你问题中“这不行”的一种有限方式。 - Paul Beckingham

1
static char **daytab;
daytab=(char**)malloc(2*sizeof(char*));
daytab[0]=(char*)(char[]){0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
daytab[1]=(char*)(char[]){0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

0

你的第二个例子的语法是多维数组字面量的语法。

多维数组不是指向数组的指针的数组。

如果一个东西的语法因其声明类型而异,则这个东西的语法也是另一种不同的东西,这将令人惊讶。

在第一个例子中,因为字符串字面量被评估为指针而不是数组值,所以该值被评估为指针的数组。因为数组字面量被评估为数组值而不是指针,所以第二个例子是一个多维数组 - 一个其元素是数组值而不是指向数组值的指针的数组。

以下代码演示了多维数组、指向数组的指针、指针的数组和指向指针的组合。其中,只有指针的数组和指向指针的指针是兼容的:

void multi_array (int x[][4], size_t len) // multidimensional array
{
    for (size_t i = 0; i < len; ++i)
        for (size_t j = 0; j < 4; ++j)
            putchar( 'a' + x[i][j] );
    putchar('\n');
}

void ptr_array (int (*x)[4], size_t len) // pointer to an array
{ ... as multi_array  }

void array_ptr (int *x[], size_t len) // array of pointers
{ ... as multi_array  }

void ptr_ptr (int **x, size_t len) // pointer to pointer
{ ... as multi_array  }

int main() {
    int a[][4] = { { 1,2,3,4 } };
    int b[] = { 1,2,3,4 };
    int* c[] = { b };

    multi_array( a, 1 );
    multi_array( (int[][4]) { { 1,2,3,4} }, 1 ); // literal syntax as value
    ptr_array( &b, 1 );
    array_ptr( c, 1 );
    ptr_ptr( c, 1 ); // only last two are the same

    return 0;
}

0
请注意,你的第一个例子也不起作用。它需要改为:
static const char *daytab[] = {
    "hello",
    "world"
};

注意 const
编辑:当我说“不起作用”时,我的意思是这是一种不良实践,容易出错,这可能更糟糕。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接