幻数java题_诗意代码 – PoemCode

读K&R之幻数、返回值和参数传递

dennis-ritchie-wikipedia.jpg

Dennis M. Ritchie

直到不久前,我都不曾认真地了解过C。大学课堂上学习过C++,在那段不长的时间里,学到的东西一直支撑着我对C的认知。等工作五年后,我重新学习C时,发现自己好生浅薄。就在自己还在读《The C Programming Language》的第二章时,网络上传来了Dennis M. Ritchie过世的消息。大师已逝,他所留下的知识将会继续惠泽着后人。我把阅读《The C Programming Language》所作的笔记整理出来,希望更多的人能够学习到Dennis M. Ritchie所建立的知识,这也算是对大师的一种纪念。

关于Magic Number

在程序中使用“幻数”是个坏习惯,它几乎不能提供任何信息。要避免这个问题,就是使用#define指令把符号名定义为一个特定的字符串。这使我想起来了在《深入Java虚拟机》一书中看到的一段话:

例如每个class文件必须是以四个同样的字节开始:魔数0xCAFEBABE。这个魔数的用处是让class文件分析器很容易分辨出某个文件有明显问题而加以拒绝。1

上面的“幻数”与“魔数”应该都是英文术语magic number的翻译,我把它理解成一个有特定意义的数字,这个数字没有名字,没人知道它代表什么意思,因此阅读程序代码的人就可能糊涂。——当然,0xCAFEBABE不会有人去读它,我只是想到了magic number这个词而已。

关于返回值

通常情况下,main函数返回值为0表示正常结束,非0表示出现异常情况或出错结束条件。

那么对于一般函数,返回值有什么约定俗成的规则吗?我想到了 Linux kernel coding style 中的两段话:

Functions can return values of many different kinds, and one of the most common is a value indicating whether the function succeeded or failed. Such a value can be represented as an error-code integer (-Exxx = failure, 0 = success) or a “succeeded” boolean (0 = failure, non-zero = success).

Functions whose return value is the actual result of a computation, rather than an indication of whether the computation succeeded, are not subject to this rule. Generally they indicate failure by returning some out-of-range result. Typical examples would be functions that return pointers; they use NULL or the ERR_PTR mechanism to report failure.

上面的文字按照是否表示执行成功来将返回值分为两大类,前者又区分为需要详细的错误码和只需要成功与否两种情形,后者则是使用NULL或ERR_PTR来标识失败。

关于参数传递

所有函数参数都是“通过值”传递,传递给被调用函数的参数值存放在临时变量中,而不是存放在原来的变量中。因此,被调用函数不能直接修改主调用函数中变量的值,而只能修改其私有的临时副本的值。

如果要让被调用函数能够修改主调用函数的变量,那么调用者需要向被调用函数提供设置值的变量的地址,而被调用函数则需要将对应的参数声明为指针类型,并通过它间接访问变量。

当把数组名作为参数时,传递给函数的值时数组起始元素的位置或地址,–它并不赋值数组元素本身。

参考文献

October 15th, 2011 in

Software| tags: C

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ioctl 幻数一般是通过定义 ioctl 命令时使用的,可以在对应的头文件中查看。在 Linux 中,很多驱动程序都会定义自己的 ioctl 命令,这些命令的幻数一般都会在对应的头文件中定义。比如,在 Linux 内核源码的 include/uapi/linux/fs.h 头文件中,可以找到以下定义: ```c #define _IOC_NRBITS 8 #define _IOC_TYPEBITS 8 #define _IOC_SIZEBITS 14 #define _IOC_DIRBITS 2 #define _IOC_NRSHIFT 0 #define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) #define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) #define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) #define _IOC_NONE 0U #define _IOC_WRITE 1U #define _IOC_READ 2U #define _IOC(dir,type,nr,size) \ (((dir) << _IOC_DIRSHIFT) | \ ((type) << _IOC_TYPESHIFT) | \ ((nr) << _IOC_NRSHIFT) | \ ((size) << _IOC_SIZESHIFT)) #define _IOC_TYPECHECK(t) (sizeof(t)) ``` 其中,_IOC_TYPEBITS 定义了 ioctl 命令的幻数长度,这里是 8 位,即一个字节。在定义具体的 ioctl 命令时,可以使用 _IO(type, nr)、_IOR(type, nr, size)、_IOW(type, nr, size)、_IOWR(type, nr, size) 等宏来定义,其中的 type 就是 ioctl 命令的幻数。比如,可以在驱动程序的头文件中找到类似以下的定义: ```c #define MYDRV_IOC_MAGIC 'm' #define MYDRV_IOC_GET_VERSION _IOR(MYDRV_IOC_MAGIC, 1, int) #define MYDRV_IOC_SET_PARAM _IOW(MYDRV_IOC_MAGIC, 2, mydrv_param_t) ``` 其中,MYDRV_IOC_MAGIC 定义了驱动程序的幻数为 'm',MYDRV_IOC_GET_VERSION 和 MYDRV_IOC_SET_PARAM 就是具体的 ioctl 命令。在用户空间程序中,可以通过 ioctl 函数调用这些命令,例如: ```c int fd = open("/dev/mydrv", O_RDWR); int version; if (ioctl(fd, MYDRV_IOC_GET_VERSION, &version) < 0) { perror("ioctl MYDRV_IOC_GET_VERSION failed"); return -1; } printf("My driver version: %d\n", version); close(fd); ``` 在这个例子中,MYDRV_IOC_GET_VERSION 就是一个 ioctl 命令,MYDRV_IOC_MAGIC 定义了这个命令的幻数。用户空间程序通过 ioctl 函数调用这个命令,并且将 version 作为参数传递给内核空间的驱动程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值