在 C 循环内使用复合文字

问题描述 投票:0回答:1

考虑这段代码:

typedef struct my_struct { int a; int b; int c; } my_struct;

void some_function(my_struct *value)
{
    // do something
}

int main(void)
{
    for (;;) {
        some_function(&(my_struct){1, 2, 3});
    }

    return 0;
}

我计划始终将

a
b
c
设置为
1
2
3
。因此,传递给
some_function
的对象将始终是相同的。在这种情况下,编译器是否在每次迭代时重新创建并重新销毁对象?或者它是否将其转换为类似的东西:

typedef struct my_struct { int a; int b; int c; } my_struct;

void some_function(my_struct *value)
{
    // do something
}

int main(void)
{
    my_struct once_and_for_all = {1, 2, 3};

    for (;;) {
        some_function(&once_and_for_all);
    }

    return 0;
}

它不会在循环中进行任何内存分配/释放,并以最佳速度运行。

我更喜欢第一种语法,因为它不太冗长,但我也担心性能。

我使用海湾合作委员会。

c performance compilation dynamic-memory-allocation
1个回答
0
投票

拆开看看。只需首先声明具有外部链接的函数,然后将函数定义保留在代码之外,这样编译器就无法对其进行任何假设:

void some_function (my_struct *value);

然后 gcc -O3 for x86 给出:

main:
        push    rbp
        push    rbx
        sub     rsp, 24
        mov     rbp, QWORD PTR .LC0[rip]
        mov     rbx, rsp
.L2:
        mov     rdi, rbx
        mov     QWORD PTR [rsp], rbp
        mov     DWORD PTR [rsp+8], 3
        call    some_function
        jmp     .L2
.LC0:
        .long   1
        .long   2

也就是说:堆栈空间被保留一次,但在循环的每一圈,值都会被复制到该空间中。由于该函数没有

const
限定参数,因此编译器无法假设该函数未修改这些值。

但是,将参数更改为

const my_struct *value
并没有改进代码。这似乎是一个错过的优化,因为我想不出 C 标准中的任何内容会迫使编译器在函数参数为
const
时一遍又一遍地更新文字。 clang 的行为是一样的。

手动优化代码修复了问题:

const my_struct* ptr = &(const my_struct){1, 2, 3};
for (;;) {
    some_function(ptr);
}

然后我们得到:

.L2:
        mov     rdi, rbx
        call    some_function
        jmp     .L2
© www.soinside.com 2019 - 2024. All rights reserved.