假设我的结构定义如下
struct my_struct
{
int num;
};
...
在这里,我有一个指向my_struct
的指针,我希望在num
上增加
void foo(struct my_struct* my_ptr)
{
// increment num
// method #1
my_ptr->num++;
// method #2
++(my_ptr->num);
// method #3
my_ptr->++num;
}
这三种递增num
的方法是否做同样的事情?
虽然我们正处于这种状态,但预增量是否比后增量更有效?
谢谢!
答案 0 :(得分:9)
前两个会产生相同的效果(当他们自己就像这样),但第三个方法是无效的C代码(你不能把++
放在那里)。
就效率而言,没有区别。你可能听到人们谈论的差异是,在C ++中,你增加了非指针数据类型,例如迭代器。在某些情况下,预增量可能会更快。
您可以使用GCC Explorer查看生成的代码。
void foo(struct my_struct* my_ptr)
{
my_ptr->num++;
}
void bar(struct my_struct* my_ptr)
{
++(my_ptr->num);
}
输出:
foo(my_struct*): # @foo(my_struct*)
incl (%rdi)
ret
bar(my_struct*): # @bar(my_struct*)
incl (%rdi)
ret
如你所见,没有任何区别。
前两个之间唯一可能的区别是当你在表达式中使用它们时:
my_ptr->num = 0;
int x = my_ptr->num++; // x = 0
my_ptr->num = 0;
int y = ++my_ptr->num; // y = 1
答案 1 :(得分:2)
如果你的唯一目的是增加num的值,那么第一个和第二个方法将产生与被调用者方法相同的意图结果。
但是,如果将代码更改为以下代码,则可以看到gcc生成的代码之间的差异(程序集级别代码):
struct my_struct
{
int num;
};
void foo(struct my_struct* my_ptr)
{
printf("\nPost Increment: %d", my_ptr->num++);
}
int main()
{
struct my_struct a;
a.num = 10;
foo(&a);
}
现在使用以下命令编译它:gcc -masm = intel -S structTest.c -o structTest.s 这要求gcc生成汇编代码:
在文本编辑器中打开structTest.s。
foo:
.LFB0:
push rbp
mov rbp, rsp
sub rsp, 16
**mov QWORD PTR [rbp-8], rdi**
mov rax, QWORD PTR [rbp-8]
mov eax, DWORD PTR [rax]
mov edx, eax
**lea ecx, [rax+1]**
mov rax, QWORD PTR [rbp-8]
mov DWORD PTR [rax], ecx
mov eax, OFFSET FLAT:.LC0
mov esi, edx
mov rdi, rax
mov eax, 0
call printf
leave
ret
.cfi_endproc
main:
.LFB1:
push rbp
mov rbp, rsp
sub rsp, 16
**mov DWORD PTR [rbp-16], 10
lea rax, [rbp-16]
mov rdi, rax
call foo**
leave
ret
.cfi_endproc
当您将操作更改为预增量时,将生成以下代码:
foo:
.LFB0:
.cfi_startproc
push rbp
mov rbp, rsp
sub rsp, 16
**mov QWORD PTR [rbp-8], rdi**
mov rax, QWORD PTR [rbp-8]
mov eax, DWORD PTR [rax]
**lea edx, [rax+1]**
mov rax, QWORD PTR [rbp-8]
**mov DWORD PTR [rax], edx**
mov rax, QWORD PTR [rbp-8]
**mov edx, DWORD PTR [rax]**
mov eax, OFFSET FLAT:.LC0
mov esi, edx
mov rdi, rax
mov eax, 0
call printf
leave
ret
.cfi_endproc
因此,您会看到在第二种情况下,编译器递增num值并将此num值传递给printf()。
就性能而言,我希望后增量更有效,因为内存位置的触摸次数更少。
在上面的代码中,重要的行标记在**之间。