2011-12-20 5 views
1

Если у меня есть структура А, определенный как:размер структуры массива

struct A { 
    char* c; 
    float f; 
    int i; 
}; 

и массив

A col[5]; 

тогда почему

sizeof(*(col+0)) 

16?

+4

См. Http://en.wikipedia.org/wiki/Data_structure_alignment – Mysticial

+1

Что такое col должно быть? –

+0

@ user695652: если вы используете MSVC, включите предупреждения до '/ WALL', и он точно скажет вам почему. –

ответ

5

На вашей платформе для хранения этой структуры требуется 16 байт, причем структура имеет тип A.

Вы должны иметь в виду, что *(col+0) идентичен col[0] так, что это только один структуры, а не весь массив из них. Если вы хотите размер массива, вы должны использовать sizeof(col).

+1

Какая структура? «A» или «A [5]»? Ваш ответ не объясняет, почему sizeof не является чем-то вроде 80. –

+0

Я ответил на вопрос, который был задан. В вашем ответе вы найдете много предположений о том, почему был задан вопрос, и я не вижу ничего в этом вопросе, чтобы оправдать эти предположения. –

+0

Он, вероятно, сделал бы это, если бы ОП спросил, почему это не что-то вроде 80. Дэвид ответил на вопрос точно и правильно, как его спрашивали. (В моем собственном ответе я потакал некоторым размышлениям о том, о чем фактически беспокоился ОП.) –

2

Ваша проблема в том, что ваша процессорная платформа использует 8-байтовое выравнивание по поплавкам. Таким образом, ваш char * будет принимать 4 (если вы используете 32-битную систему), поскольку это указатель, который является адресом. Ваш float займет 8, а ваш int займет еще 4, что составляет 16 байт.

Компиляторы часто делают определенные типы согласованными на определенных границах байтов, чтобы ускорить вычисления на используемой аппаратной платформе.

Например, если вы сделали:

struct x { 
    char y; 
    int z; 
}; 

Ваша система будет (возможно) сказать размер х был 8, дополняя полукокс из к междунар внутри структуры.

Вы можете добавить псевдокомментарии (зависит от реализации), чтобы остановить это:

#pragma pack(1) 
struct x { 
    char y; 
    int z; 
}; 
#pragma pack(0) 

который сделает размер этого равным 5.

+0

У некоторых процессоров 8-битное выравнивание по поплавкам? Я этого не слышал (хотя я не говорю, что вы ошибаетесь). Я просто предположил, что указатель был членом 8 байтов. –

+0

Я не эксперт, но меня учили до этого по какой-то причине 8-байтовое выравнивание используется для поплавков по соображениям производительности. Я бы не знал, каковы были эти причины, так что, возможно, мы можем найти ссылку где-то :) Но он может просто быть на 64-битном, что сделало бы вас определенно более правильным, чем я, - я определенно наклонил мой, предположив, что ему 32 года по какой-то причине (не знаю, почему оглядываясь). –

+0

имеет смысл. Однако ваш ответ намного лучше моего. –

5

Возможно, потому что:

  • вы на 64-битная платформа и char* занимает 8 байтов, а int и float - 4 байта,
  • вы находитесь на 32-битной платформе, а char* занимает 4 байта, но ваш компилятор решил, что массив будет быстрее, если он упадет на 4 байта. Заполнение может контролироваться большинством компиляторов с помощью #pragma pack (push, 1) и #pragma pack (pop) соответственно.

Если вы хотите быть уверены, вы можете использовать offsetof (на GCC) или создать объект и исследовать адреса своих полей членов, чтобы проверить, какие поля есть на самом деле мягкий и сколько.

2

Редактировать: Кажется, есть две части этого вопроса. «Почему sizeof(A) равно 16?» В целом, я вижу теперь, что это, вероятно, вопрос, который был предназначен. Вместо этого я отвечаю на вторую часть, то есть «Почему sizeof(*(col+0)) == sizeof(A)

col - это массив. col + 0 не имеет смысла для массивов, поэтому компилятор должен сначала преобразовать col в указатель.Тогда col фактически просто A*. Добавление нуля к указателю ничего не меняет. Наконец, вы разыменование его с * и остается простым A размера 16.

Короче говоря, sizeof(A) == sizeof(*(col+0))

PS: я не рассматривал вопрос «Почему, что один элемент массива принимает до 16 байт? " Другие ответили так хорошо.

+0

Я дам вам 1 для редактирования, Аарон и для страданий стропов и стрел :-) – paxdiablo

0

На современном процессоре x86-64 char* составляет 8 байт, float - 4 байта, int - 4 байта. Таким образом, размеры членов, добавленных вместе, равно 16. Что еще вы ожидаете? Кто-то сказал вам, что указатель - 4 байта? Потому что это справедливо только для x86-32.

4

Во-первых, ваше первоначальное объявление было неправильным (это теперь исправлено в редактировании вопроса). A - название типа; объявить массив с именем col, вы хотите

A col[5]; 

не

col A[5]; 

sizeof(*(col+0)) такой же, как sizeof col[0], который является таким же, как sizeof (A).

Это 16, потому что это размер этой структуры, для используемого вами компилятора и системы (вы не упомянули, что это такое).

Я беру это из вопроса, что вы ожидали чего-то другого, но вы этого не говорили.

Компиляторы могут вставлять байты заполнения между членами или после последнего элемента, чтобы обеспечить правильное выравнивание каждого элемента. Я нахожу 16 байтов неудивительным размером для этой структуры в 64-битной системе - и в этом конкретном случае, вероятно, нет необходимости в дополнении.

И если вы не знали, sizeof дает результат в байтах, где байт обычно (но не всегда) 8 бит.

+0

+1. Хорошее резюме различных точек. –

Смежные вопросы