Структуры в стеке (ANSI C) - PullRequest
       17

Структуры в стеке (ANSI C)

4 голосов
/ 04 октября 2010

Начав изучать Ульриха Дреппера, серия «Что каждый программист должен знать о памяти» [1], я застрял при попытке воспроизвести примеры, представленные в разделе

3.3.2 Измерения эффектов кэша

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

#include <stdio.h>
#include <stdlib.h>

#define NUMPAD 0

struct listelement
{ 
    struct listelement *next;
    long int padding[NUMPAD];
};

typedef struct listelement elem;

int main()
{
    int size_elem = sizeof(elem);
    printf("Size of a list elem: %i\n", size_elem);

    elem _1, _2, _3;

    _1.next = &_2;
    _2.next = &_3;
    _3.next = &_1;

    elem *first, *last, *curr;

    first = &_1;
    last = &_3;
    curr = &_1;

    int k=0;

    while(1)
    {
        printf("Element at %p", curr);
        for (int i=0; i<NUMPAD; i++)
        {
            (curr->padding)[i] = i+k;
            printf("%ld ", (curr->padding)[i]);
        }
        printf("\n");
        if (curr == last)
            break;
        k++;
        curr = curr->next;
    }

    return 0;
}

При запуске программы вывод:

Size of a list elem: 8
Element at 0x7fff5fbff540
Element at 0x7fff5fbff530
Element at 0x7fff5fbff520

Разница между адресами памяти, однако составляет 16, а не 8?При увеличении NUMPAD разница кажется еще больше, например, для NUMPAD = 2 я получаю разницу в 511.

Я провел тесты на MacBook Pro под управлением OSX 10.6 64bit.

[1] http://lwn.net/Articles/252125/

Обновление: я также играл с увеличением / уменьшением указателей.Кажется, он работает в 32-битном режиме, но не в 64-битном режиме.Добавление кода

first--;
printf("first-- %p\n", first);
if (first == &_2) {
    printf("Decrementing works.\n");
}

macbook:blah nils$ gcc -m32 -DNUMPAD=0 -g -std=c99 -o blah blah.c && ./blah
Size of a list elem: 4
Element at 0xbffff5b8
Element at 0xbffff5b4
Element at 0xbffff5b0
first-- 0xbffff5b4
Decrementing works.
macbook:blah nils$ gcc -DNUMPAD=0 -g -std=c99 -o blah blah.c && ./blah
Size of a list elem: 8
Element at 0x7fff5fbff530
Element at 0x7fff5fbff520
Element at 0x7fff5fbff510
first-- 0x7fff5fbff528

Интересно, как это имеет смысл ... может быть, мне следует просто поместить все структуры в массив.

Ответы [ 4 ]

2 голосов
/ 04 октября 2010

Обязательное предупреждение: в общем, вы не должны делать никаких предположений об относительном расположении в памяти независимых переменных (то есть тех, которые не заключены в массив или структуру).Компилятору разрешено размещать переменные в стеке так, как он считает нужным, с учетом ограничений выравнивания членов структуры.

Тем не менее, я думаю, вы найдете, что если вы измените:

printf("Element at %p", curr)

до

printf("Element at %p\n", curr)

Ваш вывод будет иметь гораздо больше смысла.

1 голос
/ 04 октября 2010

прочитайте это:

http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Zero-Length.html

Я подозреваю, что по умолчанию [0] равно [] и имеет размер 0, если вы компилируете с использованием C99

0 голосов
/ 04 октября 2010

Изменение

printf("%ld ", (curr->padding)[i]);

до

printf("\t%ld ", (curr->padding)[i]);

и попробуй еще раз - понял?

Вот мои результаты (на 32-битной машине) с различными значениями для NUMPAD.

test $ gcc -std=c99 -DNUMPAD=0 test.c && ./a.out 
Size of a list elem: 4
Element at 0xbfd84df8
Element at 0xbfd84df4
Element at 0xbfd84df0
test $ gcc -std=c99 -DNUMPAD=1 test.c && ./a.out 
Size of a list elem: 8
Element at 0xbff7eff4   0 
Element at 0xbff7efec   1 
Element at 0xbff7efe4   2 
test $ gcc -std=c99 -DNUMPAD=2 test.c && ./a.out 
Size of a list elem: 12
Element at 0xbf9ea260   0   1 
Element at 0xbf9ea254   1   2 
Element at 0xbf9ea248   2   3 
0 голосов
/ 04 октября 2010

Массив нулевой длины вызывает неопределенное поведение, так что вам повезло, что он не скомпилировался в system("rm -rf /"); ...

...