C++ 缺少大小与指针的数组
我通常认为以下两个原型是可以互换的:C++ 缺少大小与指针的数组,c++,c,arrays,C++,C,Arrays,我通常认为以下两个原型是可以互换的: int main(int argc, char ** argv); int main(int argc, char * argv[]); 一般来说,我认为char**argv和char*argv[]是可以互换的。然而,我也在网上看到一些东西,声称你可以像这样声明结构 struct S { int size; int ar[]; }; 然后简单地适当地malloc,以便ar可以在运行时达到您想要的大小 但我觉得这很奇怪。如果我宣布 struct S
int main(int argc, char ** argv);
int main(int argc, char * argv[]);
一般来说,我认为char**argv和char*argv[]是可以互换的。然而,我也在网上看到一些东西,声称你可以像这样声明结构
struct S {
int size;
int ar[];
};
然后简单地适当地malloc,以便ar可以在运行时达到您想要的大小
但我觉得这很奇怪。如果我宣布
struct S {
int size;
int * ar;
};
我还能做同样的事吗?我想这取决于你所说的
在结构内部使用int*ar和int-ar[]时,它们到底有什么不同?在函数原型中使用char**argv和char*argv[]怎么样?C中有不同的语义,而C++中却不同? char *和char *[]确实是相同的。事实上,以下方法将起作用:
void foo(int a1[]) {
int a2[3];
a2 = 0; // ERROR: Can't assign to an array.
a1 = 0; // OKAY: You can assign to it, because it's actually a pointer!
...
但是,您显示的结构使用灵活的数组成员。它不占空间。你不能分配给它。基本上,int[]的含义不同,这取决于它是一个成员还是一个参数。但是,在有指针的结构中,基本上可以在任何地方指出该点。char**和char*[]实际上是相同的。事实上,以下方法将起作用:
void foo(int a1[]) {
int a2[3];
a2 = 0; // ERROR: Can't assign to an array.
a1 = 0; // OKAY: You can assign to it, because it's actually a pointer!
...
但是,您显示的结构使用灵活的数组成员。它不占空间。你不能分配给它。基本上,int[]的含义不同,这取决于它是一个成员还是一个参数。但是,在有指针的结构中,基本上可以在任何地方指向该点。函数参数中使用数组类型有一条规则:它们成为指针类型。但是,该规则仅适用于函数参数
当您将未定义的尺寸替换为(例如)两个尺寸时,这一点变得非常明显:
void f(int x[2]); // equivalent to void f(int* x);
struct A {
int q[2]; // obviously not equivalent to int* q;
};
您使用的结构定义
struct S {
int size;
int ar[];
};
旨在说明任意数量的int应该跟随size成员-可能正是size元素。您不能只忽略最后一个成员,因为这可能会导致错误w.r.t.对齐和填充假设ar是一个双精度数组,您将看到问题所在
此语法是C99的一种改进,并已添加到C99中。在函数参数中使用数组类型有一条规则:它们成为指针类型。但是,该规则仅适用于函数参数
当您将未定义的尺寸替换为(例如)两个尺寸时,这一点变得非常明显:
void f(int x[2]); // equivalent to void f(int* x);
struct A {
int q[2]; // obviously not equivalent to int* q;
};
您使用的结构定义
struct S {
int size;
int ar[];
};
旨在说明任意数量的int应该跟随size成员-可能正是size元素。您不能只忽略最后一个成员,因为这可能会导致错误w.r.t.对齐和填充假设ar是一个双精度数组,您将看到问题所在
此语法是C99的一种改进,并已添加到C99中。您可以出于相同目的同时使用第一个和第二个布局,但内存中的布局将不同。对于第一个示例,假设采用32位体系结构:
[size (4 bytes)][ar (size bytes)]
对于第二个问题:
[size (4 bytes)][pointer to ar (4 bytes)][ar (size bytes)]
因此,第二种解决方案会浪费内存。您可以将第一种布局和第二种布局用于相同的目的,但内存中的布局将不同。对于第一个示例,假设采用32位体系结构:
[size (4 bytes)][ar (size bytes)]
对于第二个问题:
[size (4 bytes)][pointer to ar (4 bytes)][ar (size bytes)]
因此,第二种解决方案会浪费内存。对于看起来像数组的函数参数,有一个特例规则。任何此类参数都会调整为指向可能限定的元素类型的指针 由于该规则,这些定义:
int main(int argc, char **argv) { /* ... */ }
及
它们完全相等。函数类型的参数也有类似的规则,这些参数根据函数指针进行调整
此规则仅适用于参数声明
一个恼人的结果是,如果您声明了一个大小为的数组参数,它将被忽略:
void func(int array[42]);
真的意味着
void func(int *array);
在C99中添加了一个static关键字,我在这里不再赘述
struct S {
int size;
int ar[];
};
这是一个灵活的数组成员,是C99中添加的一项功能。它声明ar是一个数组,不是,我重复一遍,不是一个未指定大小的指针。要使用它,您必须分配足够的空间来容纳运行时需要的元素。这是作为struct hack的替代品添加到语言中的,如本手册问题2.6所述
同一常见问题解答的第6节是解释数组和指针之间经常混淆的关系的极好资源。对于看起来像数组的函数参数,有一个特例规则。任何此类参数都会调整为指向可能限定的元素类型的指针 由于该规则,这些定义:
int main(int argc, char **argv) { /* ... */ }
及
它们完全相等。函数类型的参数也有类似的规则,这些参数根据函数指针进行调整
此规则仅适用于参数声明
一个讨厌的
结果是,如果您声明一个大小为的数组参数,它将被静默忽略:
void func(int array[42]);
真的意味着
void func(int *array);
在C99中添加了一个static关键字,我在这里不再赘述
struct S {
int size;
int ar[];
};
这是一个灵活的数组成员,是C99中添加的一项功能。它声明ar是一个数组,不是,我重复一遍,不是一个未指定大小的指针。要使用它,您必须分配足够的空间来容纳运行时需要的元素。这是作为struct hack的替代品添加到语言中的,如本手册问题2.6所述
同一常见问题解答的第6节是解释数组和指针之间经常混淆的关系的极好资源。@RedAlert:不,数组是数组,在大多数上下文中,数组名称会衰减为指向其第一个元素的指针。有时间尝试分配给数组@DeDeCuultAt只是想弄乱你的想法:考虑T&[T]和T*@ GHA.ST:引用一个数组,还是我分析了一个错误?RedAlert:请不要告诉人们数组是指针。他们不是。阅读。@RedAlert:不,数组是数组,在大多数上下文中,数组名会衰减为指向其第一个元素的指针。有时间尝试分配给数组@DeDeCuultAt只是想弄乱你的想法:考虑T&[T]和T*@ GHA.ST:引用一个数组,还是我分析了一个错误?RedAlert:请不要告诉人们数组是指针。他们不是。请阅读本手册第6节。