#c 11 #variables #initializer-list #non-static
#c 11 #переменные #инициализатор-список #нестатический
Вопрос:
Visual Studio позволяет: int a[3][3] = { 0 }; как для локальной переменной, так и для нестатической переменной класса. Однако GCC допускает это только для локальных переменных, но требует, чтобы int a[3][3] = { {0} }; для инициализации переменной класса. Является ли GCC слишком ограничительным или VS слишком разрешительным?
#include <iostream>
using namespace std;
class InitArray {
public:
InitArray();
void PrintArray() const;
private:
int a[3][3] = { 0 }; // compiles in Visual Studio 2017, but not GCC
// modify to = { {0} }; to compile in GCC
InitArray::InitArray() {
PrintArray();
for (int i = 0; i < 3; i ) {
for (int j = 0; j < 3; j ) {
a[i][j] = 1;
}
}
}
void InitArray::PrintArray() const {
for (int i = 0; i < 3; i ) {
for (int j = 0; j < 3; j ) {
cout << a[i][j] << " ";
}
cout << endl;
}
}
int main() {
InitArray A;
A.PrintArray();
int a[3][3] = {0}; // OK in BOTH compilers
for (int i = 0; i < 3; i ) {
for (int j = 0; j < 3; j ) {
cout << a[i][j] << " ";
}
cout << endl;
}
return 0;
}
Комментарии:
1. Ответа нет, но совет: сделайте это правильно для платформ, для которых вы разрабатываете. Итак, вопрос в том, какой результат вы получаете при использовании
{{0}}
? И какой результат вы получаете для использования{0}
в локальном случае? Обязательно ли быть независимым от платформы?2. Какую ошибку компиляции вы получаете в GCC?
3. Даниэлю: При отображении, как показано ниже, GCC выдает ошибку: массив должен быть инициализирован с помощью заключенного в скобки инициализатора int a[3][3] = { 0 };
4. To Tobi: {{0}} работает на обеих платформах, так что это переносимый код, который я напишу в дальнейшем. В основном, вопрос был любопытным — почему компилятор GCC допускает локальные переменные по сравнению с переменными класса?
Ответ №1:
Ваш код усваивает только первую ячейку в массиве, измените строку
int a[3][3] = {0};
Для
int a[3][3] = {1};
и посмотрите на результат, только первая ячейка будет равна единице, а остальные будут равны нулю.
что касается вопроса компиляции, я компилирую с помощью GCC, и оба компилируются для меня. Разница между типами инициализации заключается в том, что
int a[3][3] = {1,2,3,4,5};
При компиляции вы получите
1 2 3
4 5 0
0 0 0
Но
int b[3][3] = {{1,2,3,4}};
Не будет компилироваться из-за
слишком много инициализаторов для ‘int [3]’ Это произойдет потому, что {{}} инициализирует только первый массив a[3] в матрице a[3][3]. Если вы хотите инициализировать все это, вам нужно будет вызвать это следующим образом:
int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
Комментарии:
1. Дэниел: Спасибо. Если бы я хотел различные ненулевые значения, то я бы явно предоставил их. Однако в ситуациях, когда мне нужны нулевые значения, я часто инициализирую первый элемент как ноль, зная, что остаток по умолчанию будет равен нулю. Экономит ввод. Знаете ли вы экземпляр (компилятор), который инициализируется ТОЛЬКО указанными значениями и не обнуляет остаток? Если это так, я бы изменил свою практику.
2. Ах, я понимаю, это немного сбивает с толку, потому что кажется, что вы хотите инициализировать весь массив равным 0. Если вы просто предполагаете, что значение по умолчанию равно 0, зачем вообще использовать = {0}?. Что касается вашего вопроса, я думаю, что все компиляторы c будут инициализировать первое значение как 0, а затем использовать default для остальных
3. Мой опыт работы с gcc следующий: int a[5]; поскольку глобальная переменная инициализируется нулями — int b[5]; поскольку стековая (локальная) переменная НЕИНИЦИАЛИЗИРОВАНА — int c[5] = {1, 2}; следует правилу частичной инициализации массива, которое инициализирует элементы как заданные и заполняет оставшуюся часть массива нулями.