Допустим есть некоторый тип SomeType и массив из элементов такого типа: SomeType array[123]. Гарантированно ли что элементы в массиве располагаются последовательно без промежутков между ними? Иными словами, верно ли что:
> Гарантированно ли что элементы в массиве располагаются последовательно без промежутков между ними?
И вот ответ:
> array[2] = *(array + 2)
Это значит, что когда мы прибавляем к указателю число, по сути, содержащийся в нём адрес увеличивается на sizeof(тип_указателя).. Повтыкай ещё раз в арифметику указтелей..
Есть дергнутые компилеры которые вставляют дополнительные промежутки элементами массива. В живую таких не встречал но об этом прямым текстом написано в документации к Oracle.
>> Есть дергнутые компилеры которые вставляют дополнительные промежутки элементами массива. В живую таких не встречал но об этом прямым текстом написано в документации к Oracle.
Т.е. не верно только в кривых компиляторах или это всё таки стандарт не гарантирует?
вобщем sizeof(array[0]) на всех компилерах возвращает расстояние между началами соседних элементов массива.
как согласуется со стандартом разлчие в размере элемента массива и размере типа этого элемента я не знаю. Я всегда пытаюсь писать без предположений о следовании компилером стандарта.
> вобщем sizeof(array[0]) на всех компилерах возвращает расстояние между началами соседних элементов массива.
Но:
The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand.
Размер определяется по типу. Значит sizeof(array[0]) == sizeof(T), где T -- тип на базе которого построен array.
>Есть дергнутые компилеры которые вставляют дополнительные промежутки элементами массива. В живую таких не встречал но об этом прямым текстом написано в документации к Oracle.
По стандарту элементы масссива всегда занимают последовательную область памяти, но компилер может алигнить элементы массива, что и делает например ГЦЦ с включенной оптимизацией.
>Допустим есть некоторый тип SomeType и массив из элементов такого типа: SomeType array[123]. Гарантированно ли что элементы в массиве располагаются последовательно без промежутков между ними? Иными словами, верно ли что:
>((char *) array) + sizeof(SomeType) == array + 1
>?
Насколько я помню сконвертив в указатель на тип с лесс стрикт алигмент то единственное что ты можешь гарантировано сделать это кастануть его назад.
А ведь если подумать, то окажется что если это утверждение не выполняется, то мы не имеем права сделать SomeType *array = malloc(n*sizeof(SomeType));. Так что стандарт обязан это гарантировать... Или я туплю под вечер?
еще там есть пример вычисления размера массива в виде sizeof(array)/sizeof(array[0]).
Но в стандарте написано что The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand.
>еще там есть пример вычисления размера массива в виде sizeof(array)/sizeof(array[0]).
>Значит sizeof(array[0]) == sizeof(SomeType)
Не очень удачный пример, в том же с99 написано для sizeof:
When applied to an operand that has array type, the result is the total number of bytes in the array.
так что никто по идее не запрещает компилятору напихать для выравнивания каждого элемента еще пустых байтов, от этого верность того выражения не изменится и при этом будет sizeof(array[0]) != sizeof(SomeType).
> и при этом будет sizeof(array[0]) != sizeof(SomeType).
пойнт был в том что sizeof(array[0]) == sizeof(SomeType) следует из фразы "The size is determined from the type of the operand." -- ведь array[0] имеет тип SomeType
>sizeof(array[0]) == sizeof(SomeType) следует из фразы "The size is determined from the type of the operand."
>ведь array[0] имеет тип SomeType
Ну и что с того ? Там написано что размер определяется из типа операнда, но только в одном случае операнд это array[0] а в другом SomeType, пусть даже и array[0] имеет тип SomeType.
Нельзя создать массив из элементов, выравненных по границе, превышающей размер элемента. Если было бы можно - то либо вся адресная арифметика перестала работать (что есть бред), либо sizeof должен выдавать размер с учётом выравнивания (что есть неправильно)
Итого, нельзя создать массив с "дырками". И данные в массивах следуют "вплотную"
> Гарантированно ли что элементы в массиве располагаются
> последовательно без промежутков между ними?
Элементы - да, полезная информация - недъ. Из-за паддинга структура
поимеет на 1 байт больше, чем инфы в ней:
struct test {
char cc [3];
int qq [3];
};
int main (int argc, char * argv []) {
int i;
struct test a [10];
printf ("%lu vs %lu\n", sizeof (struct test), 3 * sizeof (char) + 3 * sizeof (int));
printf ("%lX vs %lX\n", ((char *) a) + sizeof (struct test), a + 1);
for (i = 0; i < 10; i++) {
printf ("0x%lX (%lu)\n", (unsigned long) &a [i], (unsigned long) &a [i]);
}
return 0;
}
-----------------------------------------------------------------
16 vs 15
BFF023F0 vs BFF023F0
0xBFF023E0 (3220186080)
0xBFF023F0 (3220186096)
0xBFF02400 (3220186112)
0xBFF02410 (3220186128)
0xBFF02420 (3220186144)
0xBFF02430 (3220186160)
0xBFF02440 (3220186176)
0xBFF02450 (3220186192)
0xBFF02460 (3220186208)
0xBFF02470 (3220186224)
Причём паддинг не обязательно в конце структуры. В данном случае будед выравнено именно int qq [0], и поэтому лишний байт появится между char cc [2] и int qq [0];
Про sizeof и выравнивание в структурах четко прописано в с99 так что можно было не напрягаться :)
When applied to an operand that has structure or union type, the result is the total number of bytes in such an object, including internal and trailing padding.
>Ну и что с того ? Там написано что размер определяется из типа операнда, но только в одном случае операнд это array[0] а в другом SomeType, пусть даже и array[0] имеет тип SomeType.
Котик, ты жжешь напалмом. Представь что есть функция "void f(SomeType *a);" и есть переменные "SomeType a[10], b;". По твоему a[0] и b могут иметь разные размеры. Вопрос: как тогда работают вызовы "f(a); f(&b);"?
Так в чем проблема ? Отбросит trailing padding - размещение в внутри типа у элемента массива мменять нет смысла. Собственно вопрос и был как раз в этом
>Гарантированно ли что элементы в массиве располагаются последовательно без промежутков между ними?