声明数组时[]和()之间的C++差异

C++ difference between [ ] and ( ) when declaring an array

本文关键字:之间 C++ 差异 数组 声明      更新时间:2023-10-16

有人能告诉我这两行C++代码之间的区别吗?

int *p = new int (7);

int *p = new int [7];

除了第一个它把数字7放在p[0]中之外,我看不出任何区别,还有其他区别吗?如果有char而不是int,会发生什么?

提前谢谢。

一个是7项的数组

new int [7]

另一个只是初始化一个指向值为7 的int的指针

int *p = new int (7);

逐个查看:int *p创建一个指向int的指针。new int (7)在堆上创建一个新的int,并将值7存储在那里。=告诉计算机p应该指向新创建的内部的地址

int *p = new int [7];

同样,将其逐个处理:我们已经知道int *p创建一个指向int的指针。new int [7]创建一个int s的数组。该数组的大小为7,因此计算机为7个整数留出内存空间。在这种情况下,=告诉指针它应该指向数组的开始,也就是说,它将指向这些int s中的第一个。

当您将方括号[i]与指针(例如p[i](一起使用时,您是在告诉计算机给您p指向但偏移i的内存地址。当p指向数组的开头时,可以使用p[i]访问数组的不同部分。但是如果p指向一个int,那么p[i]就没有意义了,所以它是未定义的。一种可能的结果是,它只会偏移内存地址,并为您提供存储在int旁边的内存中的任何信息,但行为是未定义的,因此不同的编译器、计算机、操作系统/任何东西都可能导致不同的结果。

第一个只创建一个int,而不是一个数组。试图访问它之外的任何内容,例如p[1],都是未定义的行为。

不幸的是,事实并非如此,我可以访问p[I]0上有值那里…-Raz Ben Netanel 29分钟前

这是你的下一个实验,但这只是一个学习练习!和往常一样,你不应该在家里尝试这个。

int t213(void)
{
   // let me create an array of ints on the stack
   int  buff[128];
   // and initialize them to a distinctive patterh
   for (int i=0; i<128; i++) buff[i] = 0x55555555;
   void* place0 = buff; // offset 0 into buff
   // if you want, try printing buff[0] (and maybe 1 or 2 more) 
   // use hex to see the 55555555 pattern
   // next I use placement new to do something that makes everyone
   // (familiar with UB) uncomfortable ... Relax, I have an embedded 
   // software background and understand that the behavior we shall 
   // observe is not guaranteed, not even from 1 compile to the next
   int* p1 = new (place0) int(7);  // a single int, initialized to 7, 
   void* p1Addr = p1;              // at location place0
   // (no - I know your thinking about it, but don't do this.  
   // essentially because neither C nor C++ have memory layout symantics.)
   dtbAssert(p1Addr == place0)(p1Addr)(place0); // no assert occurs
                                                // both addresses are the same
   // test the soup
   std::cout << "np1      : " << std::setw(12) << std::hex << *p1     << "  @" << DTB::hexComma(p1Addr)
             << "nbuff[0] : " << std::setw(12) << std::hex << buff[0] << "  @" << DTB::hexComma(&buff[0])
             << "nbuff[1] : " << std::setw(12) << std::hex << buff[1] << "  @" << DTB::hexComma(&buff[1])
             << std::endl;
   // now spoil the soup:
   p1[1] = 0xdeadbeef; // oops - UB   NO COMPILER WARNING
   // then test the soup once more
   std::cout << "np1      : " << std::setw(12) << std::hex << *p1     << "  @" << DTB::hexComma(p1Addr)
             << "nbuff[0] : " << std::setw(12) << std::hex << buff[0] << "  @" << DTB::hexComma(&buff[0])
             << "nbuff[1] : " << std::setw(12) << std::hex << buff[1] << "  @" << DTB::hexComma(&buff[1])
             << std::endl;
   return(0);
}

由于我使用了一些私人工具,我将包括输出:

p1      :            7  @7ffe,c3bb,3910
buff[0] :            7  @7ffe,c3bb,3910
buff[1] :     55555555  @7ffe,c3bb,3914
p1      :            7  @7ffe,c3bb,3910
buff[0] :            7  @7ffe,c3bb,3910
buff[1] :     deadbeef  @7ffe,c3bb,3914

请注意标有注释"//oops-UB"的代码行。

该行使用p1[1]。但是编译器不会注意到越界索引,甚至不会发出警告。

因为它是UB,编译器生成了它想要的东西。在这种情况下(但不能保证(,就好像p1[1]存在——注意,buff[1]从55555555变为deadbeef

研究术语-退化指针