首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

给K&R的C挑个“错”

Kernighan和Ritchie合写的《The C Programming Language, Second Edition》虽然是二三十年前的书了, 但仍被认为是有关C语言的经典之作。被人饱含深情的称之为“K&R”。

题目略有些标题党,但是在C范围内,称之为错,也勉强说得过去。

01

清晰的图和令人困惑表述

在K&R第二版第五章的9和10节中有这样两个图。

俗话所,一图胜千言。两个图对于理解name和argv是大有用处的:图1中是说name是一个数组,数组的每个元素是指向字符串的指针;图2是说argv是一个指针,它指向一个数组,这个被指向的数组的元素是指向字符串的指针。

单从这两个图上看,name和argv的类型是不同的,但从C/C++中带参数的main的参数列表写法:main(int argc, char *argv[])可以看到,name和argv的声明方式是一样的。从语法上讲,这样的声明方式是在告诉编译器,name和argv都是数组,就像图1那样。那么为什么K&R会说argv是一个指针呢?

在第10节中,K&R给出的第二版本的echo函数是这样写的:

如果argv是数组的话,那么在编译时应该会出错,但是实际上这种写法可以可以正常编译运行。

这是我称之为“错”的地方:为什么明明声明了一个数组,但是却能够当做指针来用呢?

02

K&R的解释没错

K&R说argv是指针是没有问题的,只是需要加一些注解。当然,要提前说明,这部分只是笔者的理解,可能是有瑕疵的,也可能是不靠谱的。

K&R第五章的标题是“指针和数组”,这章的开篇,K&R就写到“指针和数组是紧密相关的。”但紧密相关和完全一样毕竟是两码事儿。

比如, 可以用指针打印数组。

但是如果将12行中*pa++改成*a++,将会编译不通过:

原因就是指针是一个变量,而数组名却不是。

那么为什么K&R的第二个版本的echo在编译时不报错呢?

问题的关键在函数调用。

当数组名作为函数参数时,实际传递的这个数组第一个元素的地址,也就意味着实际传递的是指针。

这就是K&R说argv是指针的原因。将带参数的main写成main(int argc, char **argv)也许是一种更好的方式。

通过阅读编译器生成的汇编代码,那么函数调用的过程就可以看得更加清楚明白。

一言以蔽之,标题所说的“错” ,实际上并不是错,在理解了指针和数组的关系后,就能够理解为什么K&R和C++ Primer对于argv的表述虽不尽相同,但本质上一样的。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180609G0QPNY00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券