Как составные литералы работают в этом коде?

У меня есть следующий код, в котором я написал две функции. Оба предназначены для получения одинакового результата. Но функция g() У которого цикл имеет другой результат, чем я ожидал, как показано ниже.

#include <stdio.h>

struct S { int i; };

void f(void)
{
    struct S *p;

    int i = 0;

    p = &((struct S) {i});
    printf("%p\n", p);

    i++;

    p = &((struct S) {i});
    printf("%p\n", p);
}

void g(void)
{
    struct S *p;

    for (int i = 0; i < 2; i++)
    {
        p = &((struct S) {i});
        printf("%p\n", p);
    }
}

int main()
{   
    printf("Calling function f()\n");
    f();

    printf("\nCalling function g()\n");
    g();
}

Выход:

Calling function f()
0023ff20
0023ff24

Calling function g()
0023ff24
0023ff24

Как получается адрес p то же самое в случае g() когда это называлось?

2 ответа

Решение

Ну, я не знаю точно, что вы пытаетесь достичь, но здесь происходит следующее:

  • (struct S){i} нотация в C99 создаст новую структуру данных в стеке
  • эта структура данных автоматически уничтожается в конце области, в которой она была создана

Так в f() На самом деле, вы создаете ДВЕ различные структуры в области действия всей функции (даже если вы назначаете их адреса одному и тому же указателю) - следовательно, два разных адреса.

void f(void)
{
    struct S *p;

    int i = 0;

    p = &((struct S) {i}); // <- first data structure, let's call it A
    printf("%p\n", p);     // <- address of the structure A printed

    i++;

    p = &((struct S) {i}); // <- second data structure, let's call it B
    printf("%p\n", p);     // <- address of the structure B printed
}                          // <- both A and B destroyed

Но в g() функционировать p создается и уничтожается во внутреннем блоке for block, и поэтому случается, что p снова и снова размещается в одной и той же позиции в стеке, давая всегда один и тот же адрес.

void g(void)
{
    struct S *p;

    for (int i = 0; i < 2; i++)
    {
        p = &((struct S) {i}); // <- data structure A created
        printf("%p\n", p);     // <- data structure A's address printed
    }                          // <- data structure A destroyed
}

Вы должны проверить код сборки, чтобы быть уверенным, но я предполагаю, что, так как p назначается локально в области видимости цикла с адресом автоматически распределенной переменной (которая выделяется в стеке), он просто повторно использует то же пространство в стеке.

В f() он не делает этого, потому что обе структуры сосуществуют в одной области, в то время как в g() Компилятор уверен, что в конце первой итерации вы не сможете использовать &((struct S) {0}),

Просто пытался из любопытства с -O2 на gcc4.2, чтобы увидеть, если что-то меняется:

Calling function f()
0x7fff5fbff388
0x7fff5fbff380

Calling function g()
0x7fff5fbff390
0x7fff5fbff390
Другие вопросы по тегам