"Обнуление" структур и массивов
struct COOLSTRUCT
{
int a;
char b;
};
COOLSTRUCT test={0};
Ведь по логике инициализации в таком случае должен инициализироватся только первый элемент массива, структуры...
Вот и возникло подозрение, что эта некая примочка то ли винды, то ли компилятора.
Собственно вопрос - гарантирует ли такой способ инициализации обнуление памяти? И соответствует ли он стандартам?
А то по старинке memset или ZeroMemory виндовую для обнуления использую...
struct COOLSTRUCT
{
int a;
char b;
};
COOLSTRUCT test={0};
Ведь по логике инициализации в таком случае должен инициализироватся только первый элемент массива, структуры...
Вот и возникло подозрение, что эта некая примочка то ли винды, то ли компилятора.
Собственно вопрос - гарантирует ли такой способ инициализации обнуление памяти? И соответствует ли он стандартам?
А то по старинке memset или ZeroMemory виндовую для обнуления использую...
А почему бы самому не взять стандарт и не почитать?
Ответ: соответствует.
А смысл этого раздела на форуме?;) Я вот к примеру 3 справочника по С/С++ перерыл перед тем как этот вопрос задать. Так что моя совесть чиста :D
struct COOLSTRUCT
{
int a;
char b;
};
COOLSTRUCT test={0};
Ведь по логике инициализации в таком случае должен инициализироватся только первый элемент массива, структуры...
Вот и возникло подозрение, что эта некая примочка то ли винды, то ли компилятора.
Собственно вопрос - гарантирует ли такой способ инициализации обнуление памяти? И соответствует ли он стандартам?
А то по старинке memset или ZeroMemory виндовую для обнуления использую...
COOLSTRUCT *test= NULL;
Ответ: соответствует.
Искал стандарт. Нашел это:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf
и еще пару подобных ресурсов.
К сожалению, нигде не встретил способа, как инициализировать массив из нескольких значений одним числом (типа int iArr[10]={0};). И в учебниках не нашёл... Можете указать источник (и желательно страницу), в котором сказано об такой инициализации.
Вопрос был по инициализации статически создаваемой структуры.
[quote=Kogrom]К сожалению, нигде не встретил способа, как инициализировать массив из нескольких значений одним числом (типа int iArr[10]={0};). И в учебниках не нашёл... [/quote]
Аналогичная ситуация. По идее, такая запись должна инициализировать только первый элемент массива. С какой стати должны обнулятся остальные, не понятно.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf
и еще пару подобных ресурсов.
Поиск "стандарт C++" по этому форуму дает несколько успешных находок.
Вот к примеру:
http://forum.codenet.ru/showthread.php?p=191393&highlight=%F1%F2%E0%ED%E4%E0%F0%F2+C#post191393
К сожалению, нигде не встретил способа, как инициализировать массив из нескольких значений одним числом (типа int iArr[10]={0};). И в учебниках не нашёл... Можете указать источник (и желательно страницу), в котором сказано об такой инициализации.
В первом посте ты говорил об обнулении, а теперь уже об "инициализации одним числом". Аппетит приходит во время еды? :)
Источник - стандарт C++.
8.5.1 Aggregates
7 If there are fewer initializers in the list than there are members in the aggregate, then each member not explicitly initialized shall be value-initialized (8.5).
[Example:
struct S { int a; char* b; int c; };
S ss = { 1, "asdf" };
initializes ss.a with 1, ss.b with "asdf", and ss.c with the value of an expression of the form int(), that is, 0. ]
Исходя из этого, инициализировать дефолтовыми значениями можно даже так:
int iArr[10] = {};
У меня не было такого поста. Автор того поста другой человек. Наверно пора заводить аватарку...
Источник - стандарт C++.
...and ss.c with the value of an expression of the form int(), that is, 0...
Исходя из этого, инициализировать дефолтовыми значениями можно даже так:
int iArr[10] = {};
Тогда можно вобще не инициализаровать, все равно int по умолчанию будет нулём. И какой смысл в этой инициализации, если можно просто написать
int iArr[10];
Только не в курсе я, чем отличается обнуление при объявлении от инициализации...
Инициализировать то походу все же нужно, т.к. int нулем делает инициализация значением по умолчанию выражения int(), а не объявление...
{
int a;
char *b;
} tst;
int noInitArr[100];
Объявление всего лишь выделяет память нужного размера.
P.S. Пустой блок {} при инициализации не прокатывает :(...
Только не в курсе я, чем отличается обнуление при объявлении от инициализации...
И я не в курсе. Может тем что для инициализации надо знать чем инициализировать, а для обнуления даже 0 не нужен. XOR по памяти и все. Угадал ?
На сколько я знаю - есть термин "инициализация" - т.е. гарантированное присвоенное какого либо определенного значения какой либо вновь созданной переменной. "Обнуление" (если конечно такой термин существует :) ) - это гарантированная установка переменной в 0.
+1
"Обнуление" (если конечно такой термин существует :) ) - это гарантированная установка переменной в 0.
Такой термин применил кто-то из авторов вопроса.
На самом деле в этом контексте существует 3 термина:
zero-initialize,
default-initialize,
value-initialize
За подробностями следует обратиться к п.8.5 стандарта.
To zero-initialize an object of type T means:
…
if T is a scalar type (3.9), the object is set to the value 0 (zero), taken as an integral constant expression, converted to T;
…
if T is an array type, each element is zero-initialized;
и далее
Every object of static storage duration shall be zero-initialized at program startup before any other initialization takes place.
То есть, насколько я понял, если ничего не делать, то массив и проинициализируется нулём (zero-initialized). Значит, если просто записать
int iArr[10];
то, согласно стандарту, все элементы массива проинициализируются нулём. А колдовства с фигурными скобками в данном случае не требуется.
и далее
То есть, насколько я понял, если ничего не делать, то массив и проинициализируется нулём (zero-initialized). Значит, если просто записать
int iArr[10];
то, согласно стандарту, все элементы массива проинициализируются нулём. А колдовства с фигурными скобками в данном случае не требуется.
А где ты видишь в записи
int iArr[10];
инициализацию?
Инициализация описывается соотв. синтаксисом, см. п.п. 8.5.1 и 8.5.2
тип имя_переменной[размер] = {};
Кроме того, меня смущает выражение:
Every object of static storage duration shall be zero-initialized at program startup before any other initialization takes place.
которое я понимаю так, что всякая переменная должна быть инициализирована нулем, до того, как будет иметь место любая другая инициализация. Но насколько я понимаю, массив нельзя инициализировать дважды, значит, происходит скрытая инициализация при объявлении.
Может это спорный вывод, но подтверждение ему я нашел только в примере
{ 1 }, { 2 }, { 3 }, { 4 }
};
initializes the first column of y (regarded as a two-dimensional array)
and leaves the rest zero.
Комментарий к примеру я понимаю примерно так: инициализируется первый столбец, все остальные элементы остаются в нуле. Заметьте, ОСТАЮТСЯ, а не устанавливаются в ноль. Хотя, может я неправильно перевожу.
"Every object of static storage duration ..."
Читаем пункт 3.7.1 стандарта, и удивляемся коду:
using namespace std;
int globalArray[20];
int main()
{
static int staticArray[20];
int localArray[20];
cout << "globalArray[2] = " << globalArray[2] << endl;
cout << "staticArray[2] = " << staticArray[2] << endl;
cout << "localArray[2] = " << localArray[2] << endl;
return 0;
}
А чтобы не путаться, рекомендую всегда инициализировать явно с помощью инициализатора.
using namespace std;
int globalArray[20];
int main()
{
static int staticArray[20];
int localArray[20] = {};
cout << "globalArray[2] = " << globalArray[2] << endl;
cout << "staticArray[2] = " << staticArray[2] << endl;
cout << "localArray[2] = " << localArray[2] << endl;
return 0;
}
Продолжаем удивляться...???..., а ведь все это описано и не раз
PS: Что можно говорить о стандарте, если даже всем известную литературу не читали, хотя переведена она вполне сносно, и в принципе является стандартом в изложении "отца".
PS2:
int iVar2();
Так в чем же разница? Почему в языке сделано именно так? И почему статические объекты изначально забиты нулями? Постигнув принцип, уже не запутаешься.
using namespace std;
int globalArray[20];
int main()
{
static int staticArray[20];
int localArray[20] = {};
cout << "globalArray[2] = " << globalArray[2] << endl;
cout << "staticArray[2] = " << staticArray[2] << endl;
cout << "localArray[2] = " << localArray[2] << endl;
return 0;
}
Продолжаем удивляться...???..., а ведь все это описано и не раз
PS: Что можно говорить о стандарте, если даже всем известную литературу не читали, хотя переведена она вполне сносно, и в принципе является стандартом в изложении "отца".
Хм... это было адресовано мне?
PS2:
int iVar2();
Так в чем же разница? Почему в языке сделано именно так? И почему статические объекты изначально забиты нулями? Постигнув принцип, уже не запутаешься.
А при чем тут статические объекты?
int iVar; - определение переменной
int iVar2(); - объявление функции
А при чем тут статические объекты?
int iVar; - определение переменной
int iVar2(); - объявление функции
Адресовано не вам.
int iVar;
int iVar2();
это обе пременные типа int, с небольшим отличием, связанным с темой топика
int iVar;
int iVar2();
это обе пременные типа int, с небольшим отличием, связанным с темой топика
Ошибаешься. :)
Читаем "всем известную литературу".
Неа, просто ошибаешься, контекст здесь не при чем.
Смотрим "всем известную литературу":
[quote=Бьярн Страустрап. Справочное руководство по C++]
8.6 Инициализация
<skip>
Заметьте, что поскольку () не является инициализатором, то "X a();" является не описанием объекта класса X, а описанием функции, не получающей значений и возвращающей X.
[/quote]
[quote=INTERNATIONAL STANDARD ISO/IEC 14882 Second edition 2003-10-15]
8.5 Initializers
<skip>
8 [Note: since () is not permitted by the syntax for initializer,
X a();
is not the declaration of an object of class X, but the declaration of a function taking no argument and returning an X. The form () is permitted in certain other initialization contexts (5.3.4, 5.2.3, 12.6.2). ]
[/quote]
Наверное, ты имел в виду вот это:
int iVar2 = int();
"Every object of static storage duration ..."
Читаем пункт 3.7.1 стандарта, и удивляемся коду:
using namespace std;
int globalArray[20];
int main()
{
static int staticArray[20];
int localArray[20];
cout << "globalArray[2] = " << globalArray[2] << endl;
cout << "staticArray[2] = " << staticArray[2] << endl;
cout << "localArray[2] = " << localArray[2] << endl;
return 0;
}
А чтобы не путаться, рекомендую всегда инициализировать явно с помощью инициализатора.
Ну вот, теперь всё разложено по полочкам.
То есть, в приведенном примере для обнуления всех массивов достаточно записать
using namespace std;
int globalArray[20];
int main()
{
static int staticArray[20];
int localArray[20] = {};
cout << "globalArray[2] = " << globalArray[2] << endl;
cout << "staticArray[2] = " << staticArray[2] << endl;
cout << "localArray[2] = " << localArray[2] << endl;
return 0;
}
А для единообразия все массивы можно инициализировать как localArray, хотя на работе программы это не должно отразиться.