[不懂就问] 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 个字节还是字符串的长度呢?

1891 次点击
所在节点    C
52 条回复
11
2015-10-28 21:29:42 +08:00
@raingolee 不科学啊

➜ ~ gcc -m32 test.c
➜ ~ ./a.out
the msg is hi iv2ex brothe msg cost 4 bytes#


gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
zhicheng
2015-10-28 21:33:17 +08:00
@raingolee
main 函数里 sizeof 是字符串长度, testChar 里 sizeof 是 char * 的长度。
如果有其它的结果或者可能,请贴出完整的代码。
aheadlead
2015-10-28 21:45:36 +08:00
参见《 C 专家编程》 Chapter 4 The Shocking Truth: C Arrays and Pointers Are NOT the Same!
raingolee
2015-10-28 21:45:44 +08:00
raingolee
2015-10-28 21:47:16 +08:00
@aheadlead 非常有帮助的回答,我去查看一下,谢谢
zhicheng
2015-10-28 21:51:17 +08:00
@raingolee
书中内容完全正确。
raingolee
2015-10-28 21:52:59 +08:00
@zhicheng
那大伙回答的却是返回编译器 int 的大小?
SErHo
2015-10-28 21:54:29 +08:00
@raingolee 哎,你截的图上不是说的很明白吗?当数组通过函数参数后,在函数体内就是指针了,此时 sizeof 返回指针的大小,不经过函数参数, sizeof 就会是数组长度。其实 C 语言根本就没有数组参数这一说法。看看这个帖子: https://lkml.org/lkml/2015/9/3/428
zhicheng
2015-10-28 21:55:20 +08:00
@raingolee

warning: sizeof on array function parameter will return size of 'char *' instead of 'char []'

你继续看书,不要再问了。
SErHo
2015-10-28 21:55:46 +08:00
@raingolee 因为在 32 位系统上,指针的大小就是 int 类型的大小, 4 个字节。
raingolee
2015-10-28 22:00:56 +08:00
@SErHo
因为在 32 位系统上,指针的大小就是 int 类型的大小, 4 个字节
这个我知道
---
好的,我继续看书去,打扰各位了,谢谢
billlee
2015-10-28 22:04:48 +08:00
C 语言中,函数参数中的数组会退化为指针,所以 sizeof(msg) 返回的是一个指针的长度
从实现上理解, C 语言不会在运行时记录数组的长度信息, sizeof 在编译时由编译器计算结果,作为一个函数参数,在编译时编译器不可能知道传进来的数组是什么长度,只能把它当成指针处理。这就是典型的静态语言。
raingolee
2015-10-28 22:07:43 +08:00
@SErHo
哎,你截的图上不是说的很明白吗?当数组通过函数参数后,在函数体内就是指针了,此时 sizeof 返回指针的大小,不经过函数参数, sizeof 就会是数组长度。其实 C 语言根本就没有数组参数这一说法。看看这个帖子: https://lkml.org/lkml/2015/9/3/428

---
我想明白了,你回答的真棒,真心感谢!!!
qian19876025
2015-10-28 22:08:03 +08:00
@raingolee 不是返回 INT 大小 而是返回 编译器所支持的指针 所占内存的大小
在 C 里面 指针大小是固定的 不关是什么类型的指针 其占用的内存都一样
为啥要这样 因为 这个指针存的是一个地址 什么地址 内存的地址 这个内存地址字长是固定的
为啥要固定 实现起来方便 简单
那为传参的时候对数组降级 其目的就是为了节省内存 方便编译器实现起来容易
使用 KISS 来理解 C 编译器的行为 以上是我对指针的理解
raingolee
2015-10-28 22:08:40 +08:00
@billlee

真心感谢认真回答的大胸弟!!!
我明白了
suikator
2015-10-28 22:12:15 +08:00
#include <stdio.h>

int main() {
int a[] = {1, 2, 3};
printf("%d\n", sizeof(a));

char b[] = {'1', '2', '3'};
printf("%d\n", sizeof(b));

char c[] = "123";
printf("%d\n", sizeof(c));
return 0;
}


哈哈
suikator
2015-10-28 22:13:41 +08:00
我已经习以为常了,哈哈
batstying
2015-10-28 22:22:31 +08:00
10 楼说的对呀,补充一句,其实在编译的时候,编译器就已经生成了 4 或者 8 来替换 sizeof(msg),而这个 sizeof(msg)表示指针这种类型占用的字节数~~,如果要求字符串可以用库函数 lstrlen ,记得字符串 0 结尾,长度+1 哦~
suikator
2015-10-28 22:27:09 +08:00
#include <stdio.h>

int main() {
int a[] = {1, 2, 3};
printf("%d,%d,%d=>%d\n", a[0],a[1],a[2],sizeof(a));

char b[] = {'1', '2', '3'};
printf("%c,%c,%c=>%d\n", b[0],b[1],b[2],sizeof(b));

char c[] = "123";
printf("%c,%c,%c=>%d\n", c[0],c[1],c[2],sizeof(c));

int temp_d = 1;
int *d = &temp_d;
*(d+1)=2;
*(d+2)=3;
printf("%d,%d,%d=>%d\n", d[0],d[1],d[2],sizeof(d));

char temp_e = '1';
char *e = &temp_e;
*(e+1)='2';
*(e+2)='3';
printf("%c,%c,%c=>%d\n", e[0],e[1],e[2],sizeof(e));

char *f = "123";
printf("%c,%c,%c=>%d\n", f[0],f[1],f[2],sizeof(f));

return 0;
}
差不多就这些了
0ver1oad
2015-10-28 23:22:19 +08:00
@raingolee 额, OSX 和 Linux 特地试了都是返回 8(64 位操作系统)

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

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

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

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

© 2021 V2EX