【问题标题】:stand alone object code in C and inline functionsC 和内联函数中的独立目标代码
【发布时间】:2019-11-15 15:02:50
【问题描述】:

当我遇到这一行时,我正在阅读来自 Inline Functions In Cinline 函数:

有时编译器需要为函数发出目标代码的独立副本,即使它是内联函数 - 例如,如果需要获取函数的地址,或者如果它可以'不要在某些特定上下文中内联,或者(也许)如果优化已关闭。 (当然,如果您使用不理解内联的编译器,您将需要目标代码的独立副本,以便所有调用都能真正工作。)

我完全不知道它想说什么,有人可以特别解释一下什么是独立目标代码

【问题讨论】:

  • 它表示该函数可能需要编译为可调用函数而不是内联。

标签: c c11


【解决方案1】:

“目标代码”一般是指编译器的输出交给链接器,作为生成机器码之前的中间步骤。

文中所说的是,如果您出于某种原因获取函数的地址,例如使用指向它的函数指针,则无法内联该函数。因为内联函数没有可以通过函数指针调用的地址。内联函数只是与调用代码链接在一起,实际上并没有进行任何函数调用。

【讨论】:

  • 编译器生成内联版本以及函数的独立代码的任何示例?
【解决方案2】:

如您所知,“内联”函数被转换为“就在那里”的机器指令。每次出现对函数的新“调用”时,这些指令都会在每个不同的地方逐字重复——函数实际上并没有被“调用”。 (内联函数很像汇编程序“宏”。)

但是,如果您要求(比如说)函数的“地址”,编译器必须生成它的非内联副本,以便能够为您提供 一个“位置它在哪里。”

【讨论】:

  • 两者都可以生成
【解决方案3】:

这里有一个例子:

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

extern inline __attribute__((always_inline)) int mul16(int x) {
    return x * 16; }

extern inline __attribute__((always_inline)) int mul3(int x) {
    return x * 3; }

int main() {

    for(int i = 0; i < 10; i ++)
    {
        int (*ptr)(int) = rand() & 1 ? mul16 : mul3;
        printf("Mul2 = %d", mul16(i));
        printf(", ptr(i) = %d\n", ptr(i));
    } 
}

https://godbolt.org/z/wDpF4j

mul16 作为单独的对象存在,并且也内联在相同的代码中。

mul16:   <----- object
        mov     eax, edi
        sal     eax, 4
        ret
mul3:
        lea     eax, [rdi+rdi*2]
        ret
.LC0:
        .string "Mul2 = %d"
.LC1:
        .string ", ptr(i) = %d\n"
main:
        push    r12
        push    rbp
        push    rbx
        mov     ebx, 0
        mov     r12d, OFFSET FLAT:mul16
.L5:
        call    rand
        test    al, 1
        mov     ebp, OFFSET FLAT:mul3
        cmovne  rbp, r12
        mov     esi, ebx
        sal     esi, 4            <-------------- inlined version
        mov     edi, OFFSET FLAT:.LC0
        mov     eax, 0
        call    printf
        mov     edi, ebx
        call    rbp
        mov     esi, eax
        mov     edi, OFFSET FLAT:.LC1
        mov     eax, 0
        call    printf
        add     ebx, 1
        cmp     ebx, 10
        jne     .L5
        mov     eax, 0
        pop     rbx
        pop     rbp
        pop     r12
        ret

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-14
    • 1970-01-01
    • 2013-02-04
    • 2010-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多