为什么VLA size的memset在不同的C++版本上的工作方式不同?

Har*_*ria -1 g++

我想在我的C++代码中使用memset.但是,代码在我的机器上意外地工作.

操作系统: - MacOS 10.12

G ++: - g ++ - 4.9(Homebrew 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;
}
Run Code Online (Sandbox Code Playgroud)

命令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));
Run Code Online (Sandbox Code Playgroud)

命令2: -

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

我得到了输出

100010

如你所见,2是正确的,1是不正确的.这种意外行为的原因是什么?

eer*_*ika 5

你的程序格式不正确.数组的大小必须是编译时常量,您使用非常量变量.

您正在使用GCC,它允许可变长度数组作为C++的语言扩展.该功能类似于C99中标准的可变长度数组,尽管AnT在注释中指出,但C++扩展与标准C VLA不同.

但是,过去曾有人建议在C++标准中添加"具有自动存储持续时间的运行时大小的数组".该提案与GCC的扩展不同,因为sizeof运行时大小的数组格式不正确(差异不一定限于此).在提案从标准草案中撤回之前,GCC 4.9在实验C++ 14模式中实施了该提议.

所以,你的程序是形成不良的所有官方C++不具有VLA标准版本,但形成很好的GNU扩展C++具有VLA,但在由GCC 4.9实现的实验标准,具有runtime-再次形成不良大小的数组,但没有sizeof.

由于数组的大小是常量,因此只需将变量声明为常量,就可以使程序格式良好:

const int size = 1e5+10;
Run Code Online (Sandbox Code Playgroud)

现在,没有使用运行时大小的数组.