方括号数组和指针数组有什么区别?

时间:2012-02-17 08:23:21

标签: c++ c arrays pointers

作为一名非C / C ++专家,我总是把方括号和指针数组视为相等。

即:

char *my_array_star;
char my_array_square[];

但我注意到,当在结构/类中使用时,它们的行为并不相同:

typedef struct {
   char whatever;
   char *my_array_star;
} my_struct_star;

typedef struct {
   char whatever;
   char my_array_square[];
} my_struct_square;

下面的行显示16,whatever需要1个字节,my_array_pointer需要8个字节。 由于填充,总结构尺寸为16。

printf("my_struct_star: %li\n",sizeof(my_struct_star));

以下行显示1,whatever占用1个字节,my_array_pointer未被考虑在内。

printf("my_struct_square: %li\n",sizeof(my_struct_square));

通过玩游戏,我注意到方括号在结构中被用作额外的空间

my_struct_square  *i=malloc(2);

i->whatever='A';
i->my_array_square[0]='B';

线条显示A:

printf("i[0]=%c\n",((char*)i)[0]);
线路显示B:

printf("i[1]=%c\n",((char*)i)[1]);

所以我不能再说方括号等于指针了。但我想了解这种行为的原因。我害怕错过这些语言的关键概念。

2 个答案:

答案 0 :(得分:25)

数组和指针的行为不一样,因为它们完全相同,只是这样。

数组是一组连续的项目,而指针是......好......指向单个项目的指针。

指向的单个项可能是数组中的第一个,因此您也可以访问其他项,但指针本身既不知道也不关心。

数组和指针通常看起来相同的原因是,在许多情况下,数组会衰减为指向该数组的第一个元素的指针。

其中一个地方就是函数调用。将数组传递给函数时,它会衰减为指针。这就是为什么像数组大小这样的东西不会明确地传递给函数。我的意思是:

#include <stdio.h>

static void fn (char plugh[]) {
    printf ("size = %d\n", sizeof(plugh)); // will give char* size (4 for me).
}

int main (void) {
    char xyzzy[10];
    printf ("size = %d\n", sizeof(xyzzy)); // will give 10.
    fn (xyzzy);

    return 0;
}

你会发现另一件事是,虽然你可以plugh++plugh--向你的心灵内容(只要你不在数组之外取消引用),你就不能使用数组xyzzy执行此操作。

在你的两个结构中,有一个主要的区别。在指针版本中,结构中有一个固定大小的指针 ,它将指向结构的外部

这就是它占用空间的原因 - 你的8字节指针与8字节边界对齐如下:

+----------------+
| 1 char variable|
+----------------+
| 7 char padding |
+----------------+
| 8 char pointer |
+----------------+

使用“无界”数组,你可以在里面结构,你可以根据需要调整它 - 你只需要在创建变量时分配足够的内存。默认情况下(即根据sizeof),大小为零:

+----------------+
| 1 char variable|
+----------------+
| 0 char array   |
+----------------+

但您可以分配更多空间,例如:

typedef struct {
   char whatever;
   char my_array_square[];
} my_struct_square;

my_struct_square twisty = malloc (sizeof (my_struct_square) + 10);

为您提供变量twisty,其中包含whatever个字符和一个名为my_array_square的十个字符的数组。

这些无界数组只能出现在结构的末尾,并且只能有一个(否则编译器不知道这些可变长度部分的开始和结束位置)并且它们专门用于允许任意大小的数组。结构的结束。

答案 1 :(得分:5)

my_array_square成员是所谓的“灵活”数组成员。没有指定大小的此类数组只能出现在结构的末尾,并且它们不会对其大小有所贡献。目的是根据需要手动分配剩余的空间。否则,数组的大小在编译时确定。

这种结构的使用模式如下:

my_struct_square *s = malloc(sizeof(my_struct_square) + 5 * sizeof(char));
...
s->my_array_square[4]; // the last element of the array

在所有其他情况下,必须在编译时知道数组的大小。甚至数组的类型也与其大小一致,即int a[20]的类型为int[20],而不仅仅是int[]

另外,理解数组和指针之间的区别至关重要。 @paxdiablo已经很清楚了。