指向结构的指针怎么可能是一个数组?

时间:2009-10-20 14:34:26

标签: c++ arrays pointers

这真是一个快速的问题。

想象一下,你有一个名为“No”的结构和以下代码:

No *v_nos; // What does this mean?

我从哪里拿出这个,他们称“v_nos”是一个数组?它不仅仅是指向结构“No”的指针吗?

感谢。

7 个答案:

答案 0 :(得分:7)

数组和指针 NOT 相同。在您的情况下,变量是指针,而不是数组。即使它们不一样,这种混淆也很常见,你会发现很多地方(包括C / C ++书籍)它们都是一样的。这意味着您应该熟悉调用指针 arrays 的人。

当开发C语言时,他们决定不是按值传递数组(可能需要大量的复制和堆栈内存),而是将数组静默转换为指向第一个元素的指针,然后将该指针传递给功能

void f( int a[3] ); // valid and misleading
// what it means:
// void f( int *a);
void test() {
   int array[3];
   f( array );
   // what it means:
   // f( & array[0] )
}

为了向后兼容,C ++保留了这个功能,你不能按值传递数组,也不能定义一个按值获取数组的函数(在这两种情况下它都将被静默转换为指向第一个元素的指针)。同时,您可以在指针上使用数组访问语法来简化指针运算,使其更加混乱:

int array[3];
int *pointer = array; // simplified: 
// int * pointer = & array[0]
pointer[2]; // equivalent to *(pointer+2) or array[2]

这意味着使用C和C ++数组中的常规函数​​会静默地衰减成指针,并且大多数人都会认为它们是相同的:数组是指向第一个元素的指针。好吧,他们不是。

在C和C ++中,它们都是不同的实体,即使某些使用模式因设计决策而相同。但它们实际上是不同的:

int array[3]; sizeof(array); // 3*sizeof(int)
int *p1=array;               // sizeof(int*), usually 4/8 bytes for 32/64 bit
int *p2=new int[3];          // sizeof(int*)

在通过函数/方法调用之后,它们都是指针:

void f( int array[3] ) { sizeof(array); } // sizeof(int*) it is really a pointer! size is ignored
void g( int *p ) { sizeof(array); }       // sizeof(int*)

在C ++中,事情变得更加有趣,因为按值传递并不是唯一可用的范例,您可以通过引用传递:

void f( int (&array)[3] ); // funny syntax to pass an array of 3 integers by reference
void testf() {
   int array1[3]; f(array1); // correct
   int array2[2]; // f(array2); compilation error, it is not an array of 3 ints!
   int *p = array1; // f(p); compilation error, it is not an array of 3 ints!
}

void g( int array[3] ); // means: void g( int *array );
void testg() {
   int array1[3]; g(array1); // correct, the array decays into & array[0]
   int array2[2]; g(array2); // correct, the array decays again
   int *p = array1; g( p );  // correct it is a pointer
}

请注意,当您定义一个按值获取数组的函数时,您实际上是在定义一个按值获取指针的函数,并且编译器不会检查函数调用的参数那个大小。这是一个已知的错误来源,也是大多数采用数组的函数都采用大小参数的原因。

最后,你不能动态创建数组,你只能动态地获取内存到指针,所以当你需要一个堆分配数组时,你实际上需要一个指向堆分配连续块的指针o存储器:

void test() {
   int *p = new int[3];
   // int array[3] = new int[3]; // error!! an array is not a pointer
   delete p;
}

最后这意味着它们不是同一个东西,但是你总是可以在指针的位置使用一个数组,它将被编译器自动转换为指向数组第一个元素的指针。通常情况下,人们会将指向一块连续内存(无论是堆栈还是堆分配)的指针引用为 array

答案 1 :(得分:3)

你是对的,但它也可以用作数组:

v_nos = new Nos[10];
v_nos[5].whatever = something;
// etc

答案 2 :(得分:3)

在实现方面,数组和指针是相同的。也就是说,数组只是作为指向数组中第一个元素的指针实现的。

之间的区别
No *v_nos;

No v_nos[3];

后者是否为该数组的3个元素留出了内存,而指针则需要使用malloc(或new)分配内存。

你仍然可以将第二个视为指针,例如*v_nos会给你第一个元素,&v_nos会给出指针的地址。

答案 3 :(得分:2)

是的,它声明(但不初始化)指向No的指针。

答案 4 :(得分:2)

它是一个指向No struct的指针。

如果他们将其称为数组,那么该指针可能指向No structs数组的第一个成员

例如

No* nos= getNosArray();//pseudocode

*nos;//first element 
*(nos+1)//2nd element;

答案 5 :(得分:0)

在C ++中,数组和指针或多或少可以互换。您可以取消引用指针的偏移量 - *(v_nos+2) - 它实际上与索引数组v_nos[2]相同。事实上,你可以使用任何一种符号,IIRC。两个示例都告诉编译器执行相同的操作:将指针递增2 *指向对象的大小,然后返回它在该位置找到的内容。

答案 6 :(得分:0)

typedef struct NO {     int x; } _NO;

int main() {     _NO * v_nos;     _NO * v_nos_array;

v_nos = new _NO(); // allocate mem for 1 struct
v_nos_array = new _NO[100]; allocate mem for 100 structs

for(1=0; 1<100; i++) v_nos_array[i].x = i; //five some value to 'x' of each struct

for(1=0; 1<100; i++) cout << v_nos_array[i].x << "\n";

}

希望你能提炼出意义。请注意,具有单个元素的数组仍然是数组。