戏说C语言变量

好玩的问题

今早帮老师去答疑,一位同学跑来问:“使用 printf 输出 %d、%c 时,后面传的参数都是变量的值,为什么 %s 看起来和它们不一样,要传一个地址?”我说:“小伙子很有前途,一般人不问这样的问题,哈哈!”

这个问题类似 Java 中基础类型传递值、对象传递引用,这么设计是为了提高效率。对于还没学完C语言的初学者来说,如果我给他扯一堆“底层设计”或“效率”等显然不合适,还极有可能掉进“值传递还是址传递”等文字游戏漩涡中,估计到了最后也只能在他听得晕头转向时搪塞一句“当初就是这么设计的”。为了尽快得给他满意的答复,我只要想办法让 %s “看起来”和其他标记一样就行了,于是写了如下的代码:

#include <stdlib.h> #include <stdio.h> typedef char STRING[80]; int main ( void ) { STRING s = "redraiment"; int i = 1; printf("%s, %d/n", s, i); return EXIT_SUCCESS; }

然后我告诉他:“因为C语言不够抽象,让你知道了太多的底层实现细节,比如你知道字符串在内存中是以字符数组的形式保存的。现在我用 typedef 定义了一个字符串类型,把这些细节屏蔽掉。通过 STRING s; 来定义一个名字是 s 的字符串类型变量,这样就和用 double d; int i; 等方式定义变量一样,你无需了解它们在内存中如何实现。此时,对于 printf 来说,%s、%d 后面跟着的 s, i 都是一回事了,它们都是变量的名字,里面保存着不同类型的数据。”很幸运,前面的话解决了他的疑惑,让我省下不少口水:P。

指针和数组的定义是个BUG

我初学C语言时,也有过类似的困惑:指针和数组别样的定义方式让我以为它们有别于普通类型。所有普通类型、自定义的结构体类型的定义方式都是 TYPE name,数据类型后面紧跟着变量名。因此,就理论上来说,你定义一个指针 int* pi,其中表示指针类型的“*”应该从属于 int。但很遗憾,实际上它从属于变量名 pi,证据就是 int* pi, i; 中,变量 i 的类型是 int,而不是一个指针。

数组同样存在这样的问题:“[]”从属于变量名。解决的办法就是将指针或数组自定义成新类型,比如:

typedef int* PINT; PINT p1, p2;

此时 p1 和 p2 都是指针。切记不能用宏来解决,它依然会存在上面的问题。

神奇的声明

每次提起变量声明时,我都会想起《C专家编程》里“骑士和公主”的故事。这是一个很绕嘴的故事(国外诗歌的名字读不习惯),我姑且用*的《沁园春·雪》打个类似的比方。“沁园春”是词牌名,它“(仄)仄平平,(仄)仄平平,仄仄仄平(韵)……”;只要按照这种词牌格式写的词,都被称作“沁园春”;这首词本身的名字称作“雪”;“雪”这首词的内容“北国风光,千里冰封,万里雪飘……”。把前面关键词(加粗)部分列于表中:

  被称作
词的名字 沁园春 “(仄)仄平平……”
“北国风光 ……”

也许你还不是很了解,我们再把文章开头的问题也罗列成表格:

  被称作
变量的类型 STRING char [80]
变量 s "redraiment"

现在清晰了,你明白我们的*也是一个编程高手,他创建了“沁园春 雪, 国情, 长沙;”等多首词。


版权声明

请尊重原创作品。转载请保持文章完整性,并以超链接形式注明原始作者“redraiment”和主站点地址,方便其他朋友提问和指正。

联系方式

我的邮箱,欢迎来信(redraiment@gmail.com
我的Blogger(子清行):http://redraiment.blogspot.com/
我的Google Sites(子清行):https://sites.google.com/site/redraiment
我的CSDN博客(梦婷轩):http://blog.csdn.net/redraiment
我的百度空间(梦婷轩):http://hi.baidu.com/redraiment

上一篇:首发|Forrester云原生开发者洞察白皮书,低代码概念缔造者又提出新的开发范式


下一篇:windows筛选键