[不懂就问] C 语言字符串指针的问题^-^

2015-10-28 20:47:58 +08:00
 raingolee

最近在看 head first c ,发现了书上有个歧义的地方,

因此上来 v2ex.py 请教各位大兄弟,感谢各位现身教学

void testChar(char msg[])
{
    printf("the msg is %s", msg);
    prinff("the msg cost %s bytes", sizeof(msg));
}

char quote[] = "hi iv2ex bro";
testChar(quote);

第二行输出的到底是 4 个字节还是字符串的长度呢?

1894 次点击
所在节点    C
52 条回复
ChiangDi
2015-10-28 23:27:57 +08:00
就是你把数组名作为参数传进去再用 sizeof 就不是返回数组元素的个数了。
fractal314
2015-10-28 23:53:07 +08:00
函数参数是数组 /结构体 /类的时候,实际传递进去的是他们的地址
raingolee
2015-10-29 00:06:20 +08:00
@fractal314
恩,最简单实用的回答了
xieyudi1990
2015-10-29 09:44:16 +08:00
@fractal314 不对. 我刚刚实际调试了下, 至少结构体是通过寄存器 /栈来传参数的. 而且 C 里边没有类这种东西 (当然你可以自己实现).

比如 x86_64 下这段代码
-------------------------------
#include <stdio.h>

typedef struct {
int i;
} S_t;

int test(S_t S)
{
printf("%d\n", S.i);
}

int main(int argc, char *argv[])
{
S_t S = {1};
test(S);
return 0;
}
-------------------------------
用 x86_64-unknown-linux-gnu-gcc 编译之后
0000000000400528 <main>:
push rbp
mov rbp,rsp
sub rsp,0x20
mov DWORD PTR [rbp-0x14],edi
mov QWORD PTR [rbp-0x20],rsi
mov DWORD PTR [rbp-0x10],0x1
mov eax,DWORD PTR [rbp-0x10]
mov edi,eax
call 400506 <test>
mov eax,0x0
leave
ret
nop

在 call test 的时候是直接传的值, 而不是引用 (地址). 因为 x86_64 前 6 个参数是通过 rdi, rsi, rdx, rcx, r8, and r9 来传参的. 这时的 info reg:
...
rdi 0x1 1
...

而 test 里边显然也是将 rdi 作为 printf 的第二个参数 (rsi):
push rbp
mov rbp,rsp
sub rsp,0x10
mov DWORD PTR [rbp-0x10],edi
mov eax,DWORD PTR [rbp-0x10]
mov esi,eax
mov edi,0x4005d4
mov eax,0x0
call 4003e0 <printf@plt>
nop
leave
ret
erenno1
2015-10-29 10:53:50 +08:00
1. sizeof 是运算符,不是函数
2. sizeof 如果和被 sizeof 的对象处于同一作用域,例如在 main 函数里对 quota 执行 sizeof ,是编译时可以预见的结果,编译器能判断出 quota 是数组
3. 函数调用属于运行时的行为,对函数传入的指针 /数组参数执行 sizeof ,统一被认定为对指针执行 sizeof ;
4. void ff ( char *quota ) 和 void ff (char quota[]) 是等同的,编译器将后者归至前者的语意,同 3
erenno1
2015-10-29 10:56:56 +08:00
更正下:
3. 函数调用属于运行时的行为,因此在编译期,对函数传入的指针 /数组参数执行 sizeof ,统一被认定为对指针执行 sizeof ;

总之, sizeof 操作应该是编译时已经搞定的事情
fxxkgw
2015-10-29 14:29:07 +08:00
能真正搞明白指针和地址的 C 语言一般不会差
ybh37
2015-10-29 14:37:37 +08:00
C 语言的学习,不能死记所谓的概念。
指针这些东西,记概念是不对的,看过汇编代码后一般会大悟。
ybh37
2015-10-29 14:40:32 +08:00
@xufang 懂的,自然懂。 不懂的,…… 呵呵~
e2real
2015-10-29 16:29:45 +08:00
论调试技能的重要性。
Keyes
2015-10-29 17:39:47 +08:00
@xufang
@ybh37

懂的自然懂+1
学 C 语言同时看着汇编是不会有错的,代码往调试器里一丢什么秘密都出来了,建议楼主不要光盯着 C 语言看,有的时候汇编比 C 更清晰,而且会让你更清晰的认识到 C 里面的某些特性“到底为什么是这样的”
handelxh
2015-10-29 21:21:21 +08:00
@raingolee 就是 sizeof(char *)的大小

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/231820

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX