《C专家编程》笔记(二)——C语言的语言特性

1. 一段代码,第一次执行时的行为与以后执行时不同:

1 generate_initializer(char * string)
2 {
3     static char separator = ‘ ‘;
4     printf("%c %s \n", separator, string);
5     separator = ‘,‘;
6 }

可用于自动生成列表。

2. 函数的可见性

1 function apple() { /* 在任何地方均可见 */ }
2 extern function pear() { /* 在任何地方均可见 */ }
3
4 static function peach() { /* 在这个文件之外不可见 */ } 

3. 这个语句p = N * sizeof * q;当中的乘号有几个?一个还是两个?

答案是一个。因为sizeof的操作数是类型名的时候,两边必须加上括号,但操作数如果是变量,则不必加括号。

那这个语句呢:apple = sizeof(int) * p;

是int类型的长度乘以p呢,还是?

4. 优先级的问题

*p.f是*(p.f),对p取f偏移作为指针,再解引用。

int *ap[]是int *(ap[]),指针的数组。

int *fp()是int *(fp()),函数指针。

val & mask != 0 是val & (mask != 0)。

c = getchar() != EOF是c = (getchar() != EOF)

msb << 4 + lsb是msb << (4 + lsb)

i = 1, 2是(i = 1), 2

5. 记住,在优先级和结合性规则告诉你哪些符号组成一个意群的同事,这些意群内部如何进行计算的次序始终是未定义的。在这个表达式里:

  x = f() + g() * h();

乘法比加法优先级高,但是f()、g()、h()的调用次序是未定义的。

6. gets()函数对读入的字符数未做检查,容易导致缓冲区溢出。所以我们应该用fgets()彻底取代gets()。

char *fgets(char * restrict s, int n, FILE * restrict stream);

7. ANSI C规定编译器词法分析中采取maximal munch strategy策略,选取能组成的最长字符序列的方案。

所以z = y+++x就被解释为z = y++ + x;

那么z = y+++++x呢?它被解释为z = y++ ++ +x,引发编译错误。因为y++返回的是右值,而自增操作只支持左值。

8. 作者给出了

a //*

//*/ b

这个例子,说在C语言里表示a/b,在C++里表示a。

但是ANSI C的新标准已经将//当成了C的行注释符号。所以这个例子已经不适用。

9. 返回一个字符串的几种方案:

  返回一个指向字符串常量的指针;(不能被改写)

  使用全局声明的数组;(浪费空间)

  使用静态数组;(不可重入,且同样耗费空间)

  在函数内显式动态分配内存,保存返回的值;(程序员必须回收内存)

  要求调用者分配内存来保存函数的返回值,同时指定缓冲区的大小(like fgets())。

时间: 2024-09-15 14:03:07

《C专家编程》笔记(二)——C语言的语言特性的相关文章

python2.7高级编程 笔记二(Python中的描述符)

Python中包含了许多内建的语言特性,它们使得代码简洁且易于理解.这些特性包括列表/集合/字典推导式,属性(property).以及装饰器(decorator).对于大部分特性来说,这些"中级"的语言特性有着完善的文档,并且易于学习. 但是这里有个例外,那就是描述符.至少对于我来说,描述符是Python语言核心中困扰我时间最长的一个特性.这里有几点原因如下: 有关描述符的官方文档相当难懂,而且没有包含优秀的示例告诉你为什么需要编写描述符(我得为Raymond Hettinger辩护一

Python网络编程笔记二

使用select模块实现IO多路复用服务端 1 import socket 2 import select 3 #windows上只支持select.select,不支持poll epoll 4 5 HOST = "127.0.0.1" 6 PORT = 9999 7 BUFFSIZE = 1024 8 ADDR = (HOST, PORT) 9 #创建服务器端监听套接字 10 tcpSocket = socket.socket(socket.AF_INET, socket.SOCK_

《C专家编程》笔记(一)——C语言的历史、K&amp;R C和ANSI C

1. C语言的许多特性是为了方便编译器设计者而建立的.于是C语言的语言特性有:数组下标从0而非1开始:C语言的基本数据类型直接与底层硬件相对应:auto关键字只对创建符号表入口的编译器设计者有意义:表达式中的数组名可以看作是指针:float被自动扩展为double(ANSI C中不再如此):不允许嵌套函数(简化了编译器):register关键字,为编译器设计者提供线索,却把包袱丢给了程序员. 2. C编译器不曾实现的一些功能必须通过其他途径实现(编译器实现的功能,如加减乘除.指针.取地址).在C

《C专家编程》读书笔记

<C专家编程>读书笔记 C语言的设计哲学: 一切工作程序员自己负责. 语言中的所有特性都不需要隐式的运行时支持. 程序员所做的都是对的. 程序员应该知道自己在干什么,并保证自己的所作所为是正确的. --第1章-- C: 穿越时空的迷雾 小即是美.事物发展都有个过程,由简入繁,不能一开始就想得太复杂,Multics, IBM的OS/360都是因此而失败. C语言的许多特性是为了方便编译器设计者而建立的.----唉,怎么这个样子 C语言的基本数据类型直接与底层硬件相对应.----确实如此 regi

JavaScript--基于对象的脚本语言学习笔记(二)

第二部分:DOM编程 1.文档象模型(DOM)提供了访问结构化文档的一种方式,很多语言自己的DOM解析器. DOM解析器就是完成结构化文档和DOM树之间的转换关系. DOM解析器解析结构化文档:将磁盘上的结构化文档转换成内存中的DOM树 从DOM树输出结构化文档:将内存中的DOM树转换成磁盘上的结构化文档 2.DOM模型扩展了HTML元素,为几乎所有的HTML元素都新增了innerHTML属性,该属性代表该元素的"内容",即返回的某个元素的开始标签.结束标签之间的字符串内容(不包含其它

编程精粹--编写高质量C语言代码(3):自己设计并使用断言(二)

接着上一遍文章<<编程精粹--编写高质量C语言代码(2):自己设计并使用断言(一)>>,继续学习如何自己设计并使用断言,来更加容易,更加不费力地自动寻找出程序中的错误. 首先看一个简单的压缩还原程序: byte* pbExpand(byte *pbFrom,byte *pbTo,size_t sizeFrom) { byte b, *bpEnd; size_t size; pbEnd=pbFrom+sizeFrom; while(pbFrom<pbEnd) { b=*pbFr

C语言控制台窗口图形界面编程(二)

下面介绍几个用于控制台窗口操作的API函数,如下: [cpp] view plaincopy //获取控制台窗口信息 GetConsoleScreenBufferInfo(); //获取控制台窗口标题 GetConsoleTitle(); //更改指定缓冲区大小 SetConsoleScreenBufferSize(); //设置控制台窗口标题 SetConsoleTitle(); //设置控制台窗口信息 SetConsoleWindowInfo(); 下面的示例程序用于说明此类函数的使用: [

Go语言学习笔记(二) [变量、类型、关键字]

日期:2014年7月19日 1.Go 在语法上有着类 C 的感觉.如果你希望将两个(或更多)语句放在一行书写,它们 必须用分号分隔.一般情况下,你不需要分号. 2.Go 同其他语言不同的地方在于变量的类型在变量名的后面.例如:不是,int a,而是 a int.当定义了一个变量,它默认赋值为其类型的 null 值.这意味着,在 var a int后,a 的 值为 0.而 var s string,意味着 s 被赋值为零长度字符串,也就是 "". 3.Go语言的变量声明和赋值 在Go中使

c语言之良好的编程习惯(二)

1.在使用变量时应该遵循一下良好的编程习惯. <1>定义有意义的变量名,有助于程序自成文档,可以减少注释. <2>用作变量名的标识符,第一个字母应该小写.大写字母开头和字母全部大写的标识符有专门的含义. <3>变量名使用多个单词可使程序具有更好的可读性,这种情况下,需要将第一个单词外的每个单词首字母大写或在每个单词之间加入下划线_以区分不同的单词. 2.只有内建数据类型和函数对象类型适用于传值调用.对于其他类型,建议使用引用常量传参,而不是传值.因为引用常量参数的方式更

C专家编程之为什么C语言把数组形参当做指针:数组/指针实参

#include<stdio.h> void print_array_test(char ca[]) { printf("ca : %s\n",ca); printf("&ca : %s\n",&ca); printf("&(ca[0]) : %s\n",&(ca[0])); printf("&(ca[1]) : %s\n",&(ca[1])); printf(&qu