выравнивание памяти __attribute __ ((align (8))) - PullRequest
10 голосов
/ 28 декабря 2010

У меня есть программа в книге

#include <stdio.h>
int main( )
{
    struct data
    {
        int a    __attribute__( ( aligned ( 8 ) ) ) ;
        char ch  __attribute__( ( aligned ( 1 ) ) ) ;
        float s  __attribute__( ( aligned ( 4 ) ) ) ;    
    } ; 
    struct data e ;
    printf ( "\n%u %u %u", &e.a, &e.ch, &e.s ) ;
    printf ( "\n%d", sizeof ( e ) ) ;
    return 0 ;
}

когда я запускаю его на Cygwin, установленном на машине с Windows 7. Я получаю вывод

2280712 2280716 2280720 16

почему этот вывод я получаю? Я ожидал выхода

2280712 2280720 2280721 13

Ответы [ 3 ]

15 голосов
/ 28 декабря 2010

A sizeof всегда кратно наибольшему выравниванию, так как на самом деле он сообщает 'step' в символах в массиве данного типа, который включает заполнение как между элементами, так что заполнение между элементами массива требуется для их выравнивания.

Схема памяти struct data будет выглядеть следующим образом:

 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 ... <--offset
|                                               |
|          struct data   (element [0])          |      (element [1])
|                                               |
|     a     |ch|::::::::|     s     |:::::::::::|     a     |ch|::::...
|                                               |
|<----------- sizeof(struct data) ------------->|

|::::| is padding
  • a со смещением 0, которое, очевидно, кратно 8;
  • chсо смещением 4, которое (также очевидно) кратно 1;
  • s имеет смещение 8, кратное 4;
  • sizeof(struct data) равно смещению [1](16) который должен быть кратным max(8,1,4) = 8
12 голосов
/ 28 декабря 2010

Атрибут aligned(N) выравнивает текущий элемент данных по адресу, кратному N, путем вставки байтов заполнения перед элементом данных.Вы, кажется, ожидаете, что это что-то делает с упаковкой, которая отличается.

Ваша структура выглядит следующим образом:

Address  Member
-------  -------
2280712  a        [address aligned on multiple of 8]
2280713  a
2280714  a
2280715  a
2280716  ch       [address aligned on multiple of 1]
2280717  (unused)
2280718  (unused)
2280719  (unused)
2280720  s        [address aligned on multiple of 4]
2280721  s
2280722  s
2280723  s
0 голосов
/ 28 декабря 2010

align (8) просто означает, что адрес & e.a будет выровнен на 8. И это (2280712).sizeof (int) предположительно равен 4, поэтому ваш символ заканчивается на 2280716 (он имеет требование выравнивания 1, поэтому нет причин для его перемещения на 2280720).Просто добавьте sizeof (int) к выводу отладки, чтобы проверить это.

Вам нужно будет изменить настройки целевого объекта сборки, если вы хотите использовать 64-битные целые числа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...