gpt4 book ai didi

C 指针和引用

转载 作者:太空宇宙 更新时间:2023-11-04 00:45:46 26 4
gpt4 key购买 nike

我想知道在 C 中调用 & 和 * 到底发生了什么。
是不是要消耗很多资源?每次我想获取相同给定变量的地址或将其保存在内存中(即缓存变量中)时,我应该调用 & 吗?与 * 相同,即当我想获取指针值时?

示例

void        bar(char *str)
{
check_one(*str)
check_two(*str)

//... Could be replaced by

char c = *str;

check_one(c);
check_two(c);
}

最佳答案

I would like to know what's really happening calling & and * in C.

没有“调用”&* 这样的东西。它们是地址运算符或解引用运算符,分别指示编译器使用对象的地址或指针指向的对象。

C 不是 C++,所以没有引用;我认为您只是在问题标题中误用了这个词。

在大多数情况下,这基本上是看待同一事物的两种方式。

通常,当您确实需要一个对象的地址时,您会使用&。由于编译器无论如何都需要使用地址来处理内存中的对象,因此没有开销。

对于使用运算符的具体含义,您必须查看编译器生成的汇编器。


示例:考虑这个简单的代码,通过 godbolt.org 反汇编:

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

void check_one(char c)
{
if(c == 'x')
exit(0);
}

void check_two(char c)
{
if(c == 'X')
exit(1);
}

void foo(char *str)
{
check_one(*str);
check_two(*str);
}

void bar(char *str)
{
char c = *str;
check_one(c);
check_two(c);
}

int main()
{
char msg[] = "something";
foo(msg);
bar(msg);
}

根据供应商和优化设置,编译器输出可能非常

clang 3.8 使用 -O2

check_one(char):                          # @check_one(char)
movzx eax, dil
cmp eax, 120
je .LBB0_2
ret
.LBB0_2:
push rax
xor edi, edi
call exit

check_two(char): # @check_two(char)
movzx eax, dil
cmp eax, 88
je .LBB1_2
ret
.LBB1_2:
push rax
mov edi, 1
call exit

foo(char*): # @foo(char*)
push rax
movzx eax, byte ptr [rdi]
cmp eax, 88
je .LBB2_3
movzx eax, al
cmp eax, 120
je .LBB2_2
pop rax
ret
.LBB2_3:
mov edi, 1
call exit
.LBB2_2:
xor edi, edi
call exit

bar(char*): # @bar(char*)
push rax
movzx eax, byte ptr [rdi]
cmp eax, 88
je .LBB3_3
movzx eax, al
cmp eax, 120
je .LBB3_2
pop rax
ret
.LBB3_3:
mov edi, 1
call exit
.LBB3_2:
xor edi, edi
call exit

main: # @main
xor eax, eax
ret

请注意 foobar 相同。其他编译器做类似的事情吗?嗯……

gcc x64 5.4 使用 -O2

check_one(char):
cmp dil, 120
je .L6
rep ret
.L6:
push rax
xor edi, edi
call exit
check_two(char):
cmp dil, 88
je .L11
rep ret
.L11:
push rax
mov edi, 1
call exit
bar(char*):
sub rsp, 8
movzx eax, BYTE PTR [rdi]
cmp al, 120
je .L16
cmp al, 88
je .L17
add rsp, 8
ret
.L16:
xor edi, edi
call exit
.L17:
mov edi, 1
call exit
foo(char*):
jmp bar(char*)
main:
sub rsp, 24
movabs rax, 7956005065853857651
mov QWORD PTR [rsp], rax
mov rdi, rsp
mov eax, 103
mov WORD PTR [rsp+8], ax
call bar(char*)
mov rdi, rsp
call bar(char*)
xor eax, eax
add rsp, 24
ret

好吧,如果有任何疑问 foobar 是等价的,至少对编译器而言,我认为是这样的:

foo(char*):
jmp bar(char*)

是他们确实 的有力论据。

关于C 指针和引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40470317/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com