【问题标题】:How could a pointer to a structure be an array?指向结构的指针怎么可能是数组?
【发布时间】:2009-10-20 14:34:25
【问题描述】:

这真是一个菜鸟快速的问题。

假设您有一个名为“No”的结构和以下代码:

No *v_nos; // What does this mean?

我从哪里得到这个,他们称“v_nos”为数组?不就是一个指向“No”结构的指针吗?

谢谢。

【问题讨论】:

  • 无需在标题中包含“[C++]”。它已经在标题中出现过一次,并作为启动标志。
  • 这意味着 v_nos 指向:a) 一个现有的 No 结构,该结构要么在别处声明,要么由 new() 实例化 b) No 结构数组的第一个元素

标签: c++ arrays pointers


【解决方案1】:

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

在开发 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++ 中,事情变得更加有趣,因为 pass-by-value 不是唯一可用的范例,您可以通过引用传递:

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
}

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

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

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

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

【讨论】:

  • 亲爱的上帝,您在这句话中绝对正确:“......大多数人会认为[数组和指针]是同一个东西:数组是指向第一个元素的指针。好吧,他们不是。”我不得不为那句话解决这么多的困惑,这甚至都不好笑。感谢您的澄清。并感谢谷歌找到这个页面。
【解决方案2】:

在实现方面,数组和指针是一样的。也就是说,数组被简单地实现为指向数组中第一个元素的指针。区别

No *v_nos;

No v_nos[3];

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

您仍然可以将第二个元素视为指针,例如,*v_nos 将提供第一个元素,&v_nos 将提供指针的地址。

【讨论】:

  • v_nos 是指针,*v_nos 给出第一个值,v_nos 是第一个值的地址。 &v_nos 是指针的地址。
  • 不错的答案,但你可以用 new 替换 malloc,问题标记为 C++ :)
  • 这是误导。数组衰减(相当容易)为指针,但无论如何它们都不相同。如果您想检查差异:void f( int (&a)[3] ) {},或int a[3]; sizeof(a) /* 3 * sizeof(int) */; int *b = new int[3]; sizeof(b); /* sizeof(int*) */
  • 不不不。数组和指针不一样,甚至“在实现方面”也不一样。 *v_nos 为您提供第一个元素,因为解引用运算符需要一个右值,这使得表达式 v_nos 衰减为指向第一个元素的指针。 &v_nos 不是指针的地址(没有指针!)而是数组的地址。那是No(*)[3] 类型的指针。不要进一步混淆。
  • 绝对不正确。数组NOT实现为指向其第一个元素的指针。数组对象类型在大多数情况下 "decays" (即被隐式转换)在表达式中使用时(但并非在所有情况下)都会变成指针值,这可能会产生 错觉数组是一个指针。然而,实际上,数组不是指针。它们是相关的,但并不相同。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      它是一个指向 No 结构的指针。

      如果他们称它为数组,则该指针可能指向无结构数组的第一个成员

      例如

      No* nos= getNosArray();//pseudocode
      
      *nos;//first element 
      *(nos+1)//2nd element;
      

      【讨论】:

        【解决方案6】:

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

        【讨论】:

        • 它们不可互换。数组可以衰减为指针,但指针永远不能转换为数组。也就是说,如果您确实需要一个数组,您将无法传递指针:void f( int (&a)[3] ) {} int main() { int *p = new int[3]; f( p ); } 将无法编译,即使 void f( int *p ) {} int main() { int a[3]; f(a); } 将通过强制数组衰减为指向第一个元素的指针来编译。
        【解决方案7】:

        typedef 结构 NO { 诠释 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";
        

        }

        希望你能把意思提取出来。请注意,具有单个元素的数组仍然是一个数组。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-06-03
          • 2012-12-07
          • 2016-06-20
          • 1970-01-01
          相关资源
          最近更新 更多