方括号数组和指针数组之间的区别是什么
What is the difference between square bracket arrays and pointer arrays?
作为一名非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: %lin",sizeof(my_struct_star));
下面的行显示1,whatever
占用1个字节,不考虑my_array_pointer
。
printf("my_struct_square: %lin",sizeof(my_struct_square));
通过四处玩耍,我注意到方括号被用作结构中的额外空间
my_struct_square *i=malloc(2);
i->whatever='A';
i->my_array_square[0]='B';
线路打击显示A:
printf("i[0]=%cn",((char*)i)[0]);
线路打击显示B:
printf("i[1]=%cn",((char*)i)[1]);
所以我不能再说方括号等于指针了。但我想了解这种行为的原因。我恐怕错过了那些语言的一个关键概念。
数组和指针的行为不一样,因为它们根本不一样。
数组是一组连续项,而指针是。。。好指向单个项的指针。
被指向的单个项很可能是数组中的第一个,因此您也可以访问其他项,但指针本身既不知道也不关心这一点。
数组和指针通常看起来是相同的原因是,在许多情况下,数组会衰减为指向该数组第一个元素的指针。
发生这种情况的地方之一是函数调用。当您将数组传递给函数时,它会衰减为指针。这就是为什么像数组大小这样的东西不会显式传递给函数的原因。我的意思是:
#include <stdio.h>
static void fn (char plugh[]) {
printf ("size = %dn", sizeof(plugh)); // will give char* size (4 for me).
}
int main (void) {
char xyzzy[10];
printf ("size = %dn", 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
的由十个字符组成的数组。
这些无界数组只能出现在一个结构的末尾,并且只能有一个(否则编译器将不知道这些可变长度部分的开始和结束位置),它们专门允许在结构的末尾使用任意大小的数组。
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[]
。
此外,理解数组和指针之间的区别也是至关重要的@帕克迪亚布罗对此做得很好。
- 动态分配的数组和静态数组之间的区别
- 在 C/C++ 中将数组作为形式参数作为 int arr[] 和 int arr[N] 传递的区别
- 删除[i] 数组和删除数组 [i] 之间的区别
- 类型测试对象的动态数组的这两个声明之间的区别?
- 动态数组和动态分配数组有什么区别?
- sizeof(空结构)和sizeof(带有空数组的结构)之间的区别?
- 初始化的多维数组,用声明初始化和声明后初始化有什么区别
- 数组的变量名和该数组的地址有什么区别?
- C/C++ 中的常量数组和静态常量数组有什么区别
- 这些在C 中初始化C数组的方式之间有区别吗?
- 将指向结构数组的指针传递给函数的区别
- 当我删除数组时,指针在哪里?指向数组的指针与数组中的元素之间的区别
- 系统堆栈中的两个函数的递归调用(将不同数量的数组作为参数传递)有什么区别
- 数组和单独初始化之间的区别
- 字符指针和字符数组之间的区别
- 在构造函数中创建数组与在 C++ 中创建声明之间的区别
- 指针阵列和指针数组的指针之间的区别
- char阵列[]和char *数组之间有什么区别
- 实例化数组的方法之间的区别
- 字符数组的 cin 和 cin.get() 之间的区别