Размеры структуры и адрес членов структуры [дубликаты]

0

2 вопроса о нижеприведенном коде:

1 Почему размер struct b 12 байтов (строка 2 вывода)? Я могу понять, почему 12 байт (для выравнивания a k на границе 4 байта), однако не должно b быть 9 байт, а не 12?

2 Почему используется оператор & для получения адреса членов char не отображающего действительный адрес? (средний вывод в последних двух строках)

#include<iostream>
using namespace std;
struct a
{
    int i;
    char j;
    int k;
};
struct b
{
    int i;
    int k;
    char j;
};
int main()
{
    a s1;
    b s2;

    cout<<sizeof(a)<<endl;
    cout<<sizeof(b)<<endl;
    cout<<sizeof(int)<<endl;
    cout<<sizeof(char)<<endl;
  cout<<&s1.i<<'\t'<<&s1.j<<'\t'<<&s1.k<<endl;
  cout<<&s2.i<<'\t'<<&s2.j<<'\t'<<&s2.k<<endl;
}

Вывод:

12
12
4
1
0x28ff14        -       0x28ff1c
0x28ff08         4A     0x28ff0c
  • 1
    Адрес char - char * . Задумайтесь об этом на мгновение. Возможно, существует operator << перегрузки operator << для потоков, который записывает такие указатели в виде строк с нулевым символом в конце, а не адресных значений. Хммм ....
  • 1
    1) также выравнивание. 2) char* рассматривается как C_String.
Показать ещё 1 комментарий
Теги:
struct

2 ответа

1
Лучший ответ

Почему размер struct b 12 байтов (строка 2 вывода)?

Он имеет int поля и поэтому имеет такое же требование выравнивания, как int four bytes, в вашем случае. В конце добавляются три байта заполнения, поэтому размер равен кратным четырем, чтобы обеспечить требуемое выравнивание.

Это применяется даже в конце структуры, так что следующий элемент массива правильно выровнен.

Почему используется оператор & для получения адреса членов char, не отображающего действительный адрес?

Поскольку << интерпретирует указатель на тип символа как указатель на строку стиля C и печатает содержимое памяти, пока не найдет нулевое значение. Чтобы напечатать адрес, введите его в несимвольный указатель:

cout << (void*)&j;
  • 0
    Является ли руководство по заполнению достаточным количеством отступов для выравнивания по наибольшему типу данных?
  • 0
    @Akash: В основном да. Точные правила немного сложнее, но обычно вам не нужно беспокоиться о мелких деталях.
Показать ещё 4 комментария
3

Если b было 9 байтов, и у вас был массив

b foo[2];

то foo[1].i не будет выровнена с четырьмя байтовыми границами.

Что касается членов char, их адрес имеет тип char *, а std::ostream имеет operator<< для тех, которые интерпретируют их как строку C-стиля. Если вы хотите увидеть их адрес, static_cast<void*>(&s1.j) - ваш друг.

EDIT: Полное раскрытие яйца на моем лице: это изначально утверждало, что некоторые компиляторы определили минимальные размеры выравнивания структуры; при расследовании это оказывается неверным. Ну, это может быть правдой, так как размер типов структур не указан в стандарте до такой степени, но обычные компиляторы, похоже, не делают этого. Извини за это.

  • 0
    Хорошо ... так что выравнивание зависит от компилятора? при использовании в структуре только символов не используется. с 1,2 или 3 символами, он использует 1,2 или 3 байта соответственно (это кодовые блоки в Windows, поэтому я думаю, MinGW)
  • 0
    О, правда - gcc под Linux делает то же самое. Я исправлю ответ, чтобы отразить это. И мне лучше проверить, что MSVC ведет себя так, как я думаю. Обновление: это не так. Тогда я лучше исправлю это.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню