Inline使功能像宏一样工作。内联与原子无关。
AFAIK inline是一个提示,gcc可能会忽略它。在内联时,内联func中的代码称为B,它被复制到调用者函数A中。A和B之间不会有任何调用。这可能会让exe更快,但代价更大。大概?如果你的内联函数很小,exe可能会变小。如果内联使优化函数A变得更加困难,则exe可能会变得更慢。如果不指定内联,gcc将在很多情况下为您进行内联决策。类的成员函数是默认的内联。您需要明确告诉gcc不要执行自动内联。另外,当优化关闭时,gcc不会内联。
链接器不会内联。因此,如果模块A extern引用了标记为内联的函数,但代码位于模块B中,则模块A将调用该函数而不是内联它。您必须在头文件中定义函数,并且必须将其声明为extern inline func foo(a,b,c)。 Its actually a lot more complicated.
inline void test(void); // __attribute__((always_inline));
inline void test(void)
{
int x = 10;
long y = 10;
long long z = 10;
y++;
z = z + 10;
}
int main(int argc, char** argv)
{
test();
return (0);
}
不是内联:
!{
main+0: lea 0x4(%esp),%ecx
main+4: and $0xfffffff0,%esp
main+7: pushl -0x4(%ecx)
main+10: push %ebp
main+11: mov %esp,%ebp
main+13: push %ecx
main+14: sub $0x4,%esp
! test();
main+17: call 0x8048354 <test> <--- making a call to test.
! return (0);
main()
main+22: mov $0x0,%eax
!}
main+27: add $0x4,%esp
main+30: pop %ecx
main+31: pop %ebp
main+32: lea -0x4(%ecx),%esp
main+35: ret
内联:
inline void test(void)__attribute__((always_inline));
! int x = 10;
main+17: movl $0xa,-0x18(%ebp) <-- hey this is test code....in main()!
! long y = 10;
main+24: movl $0xa,-0x14(%ebp)
! long long z = 10;
main+31: movl $0xa,-0x10(%ebp)
main+38: movl $0x0,-0xc(%ebp)
! y++;
main+45: addl $0x1,-0x14(%ebp)
! z = z + 10;
main+49: addl $0xa,-0x10(%ebp)
main+53: adcl $0x0,-0xc(%ebp)
!}
!int main(int argc, char** argv)
!{
main+0: lea 0x4(%esp),%ecx
main+4: and $0xfffffff0,%esp
main+7: pushl -0x4(%ecx)
main+10: push %ebp
main+11: mov %esp,%ebp
main+13: push %ecx
main+14: sub $0x14,%esp
! test(); <-- no jump here
! return (0);
main()
main+57: mov $0x0,%eax
!}
main+62: add $0x14,%esp
main+65: pop %ecx
main+66: pop %ebp
main+67: lea -0x4(%ecx),%esp
main+70: ret
可以肯定的唯一功能是原子是gcc atomic builtins。可能很简单的一个操作码汇编指令也是原子的,但它们可能不是。根据我的经验,至今在6x86设置或读取32位整数是原子。您可以通过查看生成的汇编代码来猜测一行c代码是否可以是原子的。
上述代码是在32位模式下编译的。你可以看到,long long需要2个操作码加载。我猜这不是原子的。整数和长整数需要一个操作码设置。可能是原子的。 y ++是用addl实现的,这可能是原子的。我一直在说,可能是因为CPU上的微代码可能使用多个指令来实现一个操作,并且这个知识高于我的薪酬等级。我假设所有的32位写入和读取都是原子的。我认为增量不是,因为它们通常是通过读取和写入来执行的。
但检查了这一点,在64位
! int x = 10;
main+11: movl $0xa,-0x14(%rbp)
! long y = 10;
main+18: movq $0xa,-0x10(%rbp)
! long long z = 10;
main+26: movq $0xa,-0x8(%rbp)
! y++;
main+34: addq $0x1,-0x10(%rbp)
! z = z + 10;
main+39: addq $0xa,-0x8(%rbp)
!}
!int main(int argc, char** argv)
!{
main+0: push %rbp
main+1: mov %rsp,%rbp
main+4: mov %edi,-0x24(%rbp)
main+7: mov %rsi,-0x30(%rbp)
! test();
! return (0);
main()
main+44: mov $0x0,%eax
!}
main+49: leaveq
main+50: retq
我猜addq可能是原子在编译时。
请问您是否可以格式化您的代码 – Elalfer 2011-01-27 04:27:23
修复了代码格式和标题。 – 2011-01-27 04:28:12