章节名称 — 目录
1. 场景一:作为函数参数(它们是等价的)
书里开头提到,在函数的参数列表里,char s[] 和 char *s 完全是一回事 。
- 为什么? 因为 C 语言为了效率,不会在你调用函数时把整个数组“复印”一份传进去。
- 真相: 无论你写成数组形式还是指针形式,编译器都会偷偷把数组名转换成指向首元素的 指针 。所以,你在函数里改
s[0],改的就是外面的原件。
2. 场景二:extern 声明(这是最危险的陷阱!)
这是书里强调的“天渊之别”。如果你在 A 文件定义了一个数组,在 B 文件想引用它,声明方式错一点程序就会崩。
| 声明方式 | 含义 | 就像是… |
|---|---|---|
extern char hello[]; | “在别处有一块内存空间 ,名字叫 hello,里面存着字符。” | 你直接找到了那座房子 。 |
extern char *hello; | “在别处有一个指针变量 ,名字叫 hello,里面存着一个地址。” | 你找到了一个信箱 ,里面写着房子的地址。 |
翻车现场:
如果你明明定义的是数组 char hello[] = "abc",却声明成了 extern char *hello。
- 当你使用
*hello的时候,编译器会去hello的前几个字节里找“地址”。 - 它会把
"abcd"的 ASCII 码误认为是一个内存地址。 - 结果:程序试图去访问一个乱七八糟的地址,直接 Segment Fault (段错误) 挂掉。
3. 场景三:main 函数的 argv
书里提到了 char *argv[] 和 char **argv 的等价性。
argv是一个 指针的数组 (存了一堆字符串地址的列表)。- 根据场景一的逻辑,当它作为
main函数的参数时,它会“退化”成指向首元素的指针。 - 因为数组里的每个元素本身就是
char *(指针),所以指向这些元素的指针就是 “指向指针的指针” ,即char **。