V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
caizixian
V2EX  ›  C

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

  •  
  •   caizixian · 2015-03-30 18:34:20 +08:00 · 1551 次点击
    这是一个创建于 3532 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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;
    }
    

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

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

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

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

    @ffffwh
    @fliar
    @tabris17
    @area346 谢谢指教
    zeroten
        10
    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
        11
    gongpeione  
       2015-03-30 19:38:26 +08:00
    @zeroten 好图好图
    wecan
        12
    wecan  
       2015-03-30 20:11:58 +08:00 via Android
    @zeroten 有没有比较过效率呢
    caizixian
        13
    caizixian  
    OP
       2015-03-30 20:15:40 +08:00
    @zeroten
    @wecan
    @gongpeione 我之前遇到了问题是输了个几千的n,然后有几个数组。
    Debug的时候发现修改a数组里的东西时,居然改的是b数组的某个
    wecan
        14
    wecan  
       2015-03-30 20:45:13 +08:00 via Android
    @caizixian 可以把指针减一下除以sizeof(int)看下
    ThomasZ
        15
    ThomasZ  
       2015-03-30 22:07:48 +08:00
    这个gcc下编译不过啊, array的长度不能在运行时期生成, 那样的要申请内存来完成
    WKPlus
        16
    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
        17
    inevermore  
       2015-03-30 23:11:33 +08:00
    int 加上const可以编译通过,C++对于const int采用类似内联的方式展开
    FrankHB
        18
    FrankHB  
       2015-03-30 23:26:38 +08:00   ❤️ 3
    @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
        19
    WKPlus  
       2015-03-30 23:42:06 +08:00
    @FrankHB 哈,谢谢提醒,是我看错了,VLA在C11里面才是optional的
    caizixian
        20
    caizixian  
    OP
       2015-03-31 12:02:30 +08:00
    @FrankHB 感谢解释。

    @all 学习了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2940 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 02:45 · PVG 10:45 · LAX 18:45 · JFK 21:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.