Почему memset для размера VLA работает по-разному на разных версиях C ++? - PullRequest
0 голосов
/ 08 января 2019

Я пытаюсь использовать memset в моем коде C ++. Однако код работает неожиданно на моей машине.

ОС: - 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;
}

Команда 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 голосов
/ 08 января 2019

Ваша программа некорректна. Размер массива должен быть постоянным времени компиляции, вы используете непостоянную переменную.

Вы используете GCC, который допускает использование массивов переменной длины в качестве расширения языка C ++. Эта функция аналогична массивам переменной длины, стандартным в C99, хотя, как указывает AnT в комментарии , расширение C ++ отличается от стандартного VLA C.

Однако было предложение добавить «Массивы размера времени выполнения с автоматической продолжительностью хранения» в стандарт C ++. Это предложение отличается от расширения GCC тем, что sizeof массива размера во время выполнения является плохо сформированным (различия не обязательно ограничиваются этим). GCC 4.9 реализовал это предложение в экспериментальном режиме C ++ 14 до того, как предложение было изъято из стандартного проекта.

Итак, ваша программа некорректна во всех официальных стандартных версиях C ++, которые не имеют VLA, но хорошо сформированы в расширенном GNU C ++, который имеет VLA, но снова плохо сформированы в экспериментальном стандарте, реализованном GCC 4.9, который есть массивы размера во время выполнения, но для них нет sizeof.

Поскольку размер массива постоянен, вы можете сделать свою программу правильно сформированной, просто объявив переменную константу:

const int size = 1e5+10;

Теперь массив размера времени выполнения не используется.

0 голосов
/ 08 января 2019

Причина в том, что VLA (массивы переменной длины) не поддерживаются в C ++. В любом случае, некоторые компиляторы их поддерживают, потому что у них уже есть код для C99.

Но так как он не определен для C ++, то, что вы получаете, является случайным. Например, sizeof может не быть вызовом функции в C ++. В C99 это для VLA. Но в C ++ это может быть не так. Это означает, что он вернет фиксированное число, которое может быть не совсем тем, что вы ожидаете.

...