为什么这样开数组会出问题?

2015-03-30 18:34:20 +08:00
 caizixian

6年前的疑问了,今天突然想到。平常都没写C/C++,所以请教一下。

#include <iostream>
using namespace std;
int main()
{
    int n;
    cin>>n;
    int a[n];
    for (int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    return 0;
}

没记错的话貌似数组会越界

1564 次点击
所在节点    C
20 条回复
area346
2015-03-30 18:38:44 +08:00
……a[n],是在编译时期就要知道要申请的长度吧……这么做确定可以编译么...要是能通过也是个大小为0的数组- -
tabris17
2015-03-30 18:45:42 +08:00
数组长度是固定的,要在编译期确定。

运行时确定数组长度使用 new 或者 malloc
fliar
2015-03-30 18:49:47 +08:00
变长数组要用new
GtDzx
2015-03-30 18:52:07 +08:00
当年是不行 最新的C++11好像支持了?
icenan2
2015-03-30 18:53:08 +08:00
6年后这样写应该是ok的吧
fliar
2015-03-30 18:53:29 +08:00
int[] a = new int[n];
删除:
delete[] a;
gongpeione
2015-03-30 18:55:20 +08:00
c99已经支持变长数组0 0
ffffwh
2015-03-30 19:15:57 +08:00
这个数组是分配在栈(函数调用栈)上的,调用函数压栈,函数返回出栈。于是编译器要事先知道数组大小以确定压栈大小。

int *a = new int[n]; 的话是分配在堆上的。函数调用栈上只留一个它的指针。不用了要手动删除。
caizixian
2015-03-30 19:18:06 +08:00
@GtDzx
@icenan2
@gongpeione 原来是这样

@ffffwh
@fliar
@tabris17
@area346 谢谢指教
zeroten
2015-03-30 19:35:04 +08:00
@gongpeione
我来补图

#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int a[n];
for (int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}

for (int i=0;i<n;i++)
{
printf("%d",a[i]);
}
return 0;
}
gongpeione
2015-03-30 19:38:26 +08:00
@zeroten 好图好图
wecan
2015-03-30 20:11:58 +08:00
@zeroten 有没有比较过效率呢
caizixian
2015-03-30 20:15:40 +08:00
@zeroten
@wecan
@gongpeione 我之前遇到了问题是输了个几千的n,然后有几个数组。
Debug的时候发现修改a数组里的东西时,居然改的是b数组的某个
wecan
2015-03-30 20:45:13 +08:00
@caizixian 可以把指针减一下除以sizeof(int)看下
ThomasZ
2015-03-30 22:07:48 +08:00
这个gcc下编译不过啊, array的长度不能在运行时期生成, 那样的要申请内存来完成
WKPlus
2015-03-30 23:07:43 +08:00
C99支持VLA,但是C++11标准说明了VLA是optional的,也就是说支不支持VLA是编译器说了算的
https://groups.google.com/forum/#!topic/comp.std.c/AoB6LFHcd88

还有一个Scott Meyers发的thread:
https://groups.google.com/forum/#!topic/comp.std.c++/K_4lgA1JYeg
inevermore
2015-03-30 23:11:33 +08:00
int 加上const可以编译通过,C++对于const int采用类似内联的方式展开
FrankHB
2015-03-30 23:26:38 +08:00
@GtDzx C++11没有支持VLA。
@icenan2 不考虑扩展,最快也许两年后。
@gongpeione 题主明显没有用C。C++没有这项特性。
@ffffwh 不要拿实现偷换语义。即便典型实现如此,C和C++都本身不管所谓的栈和堆。顺便,重定义operator new[]还就是能保证new不分配在堆上(如果找得到替代的自由存储)。
@WKPlus 你记错了,C99是支持VLA(variable length array),但改成optional的是C11而不是C++11。
ISO C++从来都没考虑完整支持VLA,一个主要原因是运行时计算sizeof不可接受。
C++1y曾经考虑支持不包括这项特性的VLA的简化版本ARB(array of runtime bound),但是考虑进度问题以及为了并行,2012年一大堆标准化工作分离为TS(Technicle Specification)直接从working draft里移除,结果C++14也没有包括这些特性。
最早的话也许C++17能正式支持。
顺便,GNU C++扩展是支持VLA的,g++默认-std=gnu++98能过。作为扩展,gcc默认的-std=gnu89也支持。
WKPlus
2015-03-30 23:42:06 +08:00
@FrankHB 哈,谢谢提醒,是我看错了,VLA在C11里面才是optional的
caizixian
2015-03-31 12:02:30 +08:00
@FrankHB 感谢解释。

@all 学习了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/180395

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX