Байты членов разыменованного объединения не совпадают - PullRequest
0 голосов
/ 24 ноября 2018

Из учебника в learnc я экспериментирую с некоторыми действительно базовыми вещами, касающимися указателей и союзов.В приведенном ниже коде я создаю struct operator с анонимным union, состоящим из float, double и int.Поскольку double является самым большим из восьми байтов, я ожидаю увидеть, что у моего int есть восемь байтов, что и происходит.Тем не менее, они не совпадают с байтами double!

typedef enum {
    INTEGER = 0,
    FLOAT = 1,
    DOUBLE = 2,
} operator_type;

typedef struct operator {
    operator_type type;

    union {
        int intNum;
        double doubleNum;
        float floatNum;
    };
} operator_t;

int main() {

    operator_t op;
    op.type = FLOAT;
    op.floatNum = 3.14f;

    printf("op.intNum = %i\nop.doubleNum = %f\nop.floatNum = %f\n", op.intNum, op.doubleNum, op.floatNum);

    printf("op.intNum [%i, %i, %i, %i, %i, %i, %i, %i, %i]",
           &(op.intNum) + 0,
           &(op.intNum) + 1,
           &(op.intNum) + 2,
           &(op.intNum) + 3,
           &(op.intNum) + 4,
           &(op.intNum) + 5,
           &(op.intNum) + 6,
           &(op.intNum) + 7,
           &(op.intNum) + 8
           );

    printf("op.doubleNum [%i, %i, %i, %i, %i, %i, %i, %i, %i]",
           &(op.doubleNum) + 0,
           &(op.doubleNum) + 1,
           &(op.doubleNum) + 2,
           &(op.doubleNum) + 3,
           &(op.doubleNum) + 4,
           &(op.doubleNum) + 5,
           &(op.doubleNum) + 6,
           &(op.doubleNum) + 7,
           &(op.doubleNum) + 8
    );

    return 0;
}

Я получаю вывод:

op.intNum [-13304, -13300, -13296, -13292, -13288, -13284, -13280, -13276, -13272]
op.doubleNum [-13304, -13296, -13288, -13280, -13272, -13264, -13256, -13248, -13240]

Разве не &(op.intNum) == &(op.doubleNum) == &(op.floatNum)?

Ответы [ 3 ]

0 голосов
/ 25 ноября 2018

&(op.intNum) + 1 - это адрес сразу после конца op.intNum.

То есть, если op.intNum находится по адресу A, а sizeof op.intNum равен 4, то написанное вами выражение имеетзначение A + 4.

Это следствие того, как определяется арифметика указателя.

0 голосов
/ 25 ноября 2018

В вашем случае вы не разыменовываете union, для разыменования вам нужно объявить op как указатель.

К вашему сведению:

В вашем коде вы печатаете

  • адрес члена int, а sizeof (int) равен 4 в вашей архитектуре, поэтому приращение на1, ваш адрес будет address + sizeof (int)

  • адрес двойного члена и sizeof (double) в 8, в этом случае каждый после каждого приращения ваш адрес будет address + 8

Надеюсь, это поможет.

0 голосов
/ 25 ноября 2018

Не должны &(op.intNum) == &(op.doubleNum) == &(op.floatNum)?

Да, они должны, и они есть.

Для того, чтобынапечатайте адрес, используйте %p в качестве спецификатора формата и приведите его к void*.Подробнее читайте в Как напечатать переменные адреса в C?

Редактировать: Почему я должен преобразовать свой адрес памяти в (void *)?

...