为什么VLA大小的memset在不同的C ++版本上工作不同?

时间:2019-01-08 16:58:13

标签: g++

我正在尝试在我的C ++代码中使用memset。但是,代码在我的机器上无法正常工作。

OS:-MacOS 10.12

G ++:-g ++-4.9(自制GCC 4.9.4_1)4.9.4

#include <bits/stdc++.h>
#define ll long long
using namespace std;

int main(){
    int test;
    cin >> test;
    while(test--){
        int size = 1e5+10;
        int arr[size];
        memset(arr,0,sizeof(arr));
        int cnt = 0;
        for(ll i = 0; i < size; i++){
            if(arr[i]==0) cnt++;
        }
        cout << cnt << endl;
    }
    return 0;
}

命令1:-

g++ -std=c++14 file.cpp然后是./a.out

我得到了输出

96835

有警告

file.cpp: In function 'int main()':
file.cpp:17:32: warning: taking sizeof array of runtime bound [-Wvla]
         memset(arr,0,sizeof(arr));

命令2:-

g++ -std=c++11 file.cpp然后是./a.out

我得到了输出

100010

如您所见,2是正确的,1是不正确的。这种意外行为的原因可能是什么?

2 个答案:

答案 0 :(得分:5)

您的程序格式错误。数组的大小必须是编译时间常数,您可以使用非常数变量。

您正在使用GCC,它允许将可变长度数组作为C ++的语言扩展。该功能类似于C99中标准的可变长度数组,不过正如AnT在a comment中指出的那样,C ++扩展名不同于标准C VLA。

但是,过去曾经有人提议将“具有自动存储持续时间的运行时大小的数组”添加到C ++标准中。该提议与GCC的扩展不同之处在于,运行时大小的数组的sizeof格式不正确(差异不必局限于此)。在将该提案从标准草案中撤回之前,GCC 4.9以实验性C ++ 14模式实施了该提案。

因此,您的程序在所有不带VLA的正式C ++标准版本中格式不正确,但在具有VLA的GNU扩展C ++中格式正确,但在GCC 4.9实现的实验标准中又格式不正确具有运行时大小的数组,但没有sizeof

由于数组的大小是常量,因此只需声明变量常量即可使程序格式正确:

const int size = 1e5+10;

现在,不使用运行时大小的数组。

答案 1 :(得分:1)

原因是因为C ++不支持VLA(可变长度数组)。某些编译器仍然支持它们,因为它们已经具有C99的代码。

但是由于未为C ++定义,因此获得的是随机的。例如,sizeof可能不是C ++中的函数调用。在C99中,它适用于VLA。但是在C ++中可能不是。这意味着它将返回一个固定数字,可能与您期望的不完全相同。