读书笔记(4)"/>
C程序设计语言读书笔记(4)
被调用函数通过return 语句向调用者返回值,return语句的后面可以跟任何表达式:return (表达式);
在必要时,表达式将被转化为函数的返回值类型。
声明语句:
double sum, atof(char []);
表明sum是一个double 类型的变量,atof函数带有一个char[]类型的参数,且返回一个double类型的值。
C语言不允许在一个函数中定义其他的函数。
对于某些中等规模的程序,最好只用一个头文件存放程序中各部分共享的对象,需要用时需要用#include包含进来。
用static声明限定外部变量与函数,可以将其后声明的对象的作用域限定为编译源文件的剩余部分。
示例程序:
//file1: static int staticNum ; int num ;static int getStaticNum() {return staticNum; }int getNum() {return num; }
//file2: #include <stdio.h> extern int staticNum; extern int getStaticNum();extern int num; extern int getNum();int main() { // printf("%d\n", staticNum); // printf("%d\n", getStaticNum()); printf("%d\n",num);printf("%d\n",getNum());return 0; }
如果将file2文件的注释取消,那么是不能通过编译的。因为staticNum和getStaticNum函数都是static的,所以它们的作用域只能在file1中。
以上程序的输出是两个0,所以static变量如果没有赋初始值,那默认就是0。
static类型的内部变量是一种只能在某个特定函数中使用但一直占据存储空间的变量。
示例程序:
#include <stdio.h> void testStaticVal() {static int num = 3;num++;printf("%d\n", num); } int main() {testStaticVal();testStaticVal();testStaticVal();return 0; }
以上程序的输出数字是4 5 6。所以static变量只在第一次进入程序块时被初始化。并且具有记忆性。
变量的声明或初始化只能在做花括号开始,即左花括号后要集中声明或初始化一批变量。如下的写法是错的:
int main() {int a = 1;a = a + a;int b = 9;return 0; }
因为int b = 9没有紧跟在int a = 1之后。
变量初始化的表达式必须为常量表达式。
数组初始化:
如果初始化表达式的个数比数组元素少,则对外部变量,静态变量和自动变量来说,没有初始化表达式的元素将被初始化为0。而局部变量数组的值未定义。
宏替换:
宏定义的形式如下:
#define 名字 替换文本
可以把一个较长的宏定义分成若干行,这时需要在待续的行末加上一个反斜杠符\ 。
#define指令定义的名字的作用域从其定义开始,到被编译的源文件的末尾行结束。
宏定义中也可以使用前面出现的宏定义。
替换只对记号进行,对括在引号中字符串不起作用。例如,如果YES是一个通过#define指令定义的名字,则在printf("YES")或YESMAN中将不执行替换。
宏定义可以带参数:
比如#define max(A, B) ((A) > (B) ? (A) : (B))
语句:
x = max(p + q, r + s);
被替换为下列形式:
x = ((p + q) > (r + s) ? (p + q) : (r + s));
使用带参数宏要注意一些问题,请看:
示例程序:
#include <stdio.h> #define max(A, B) ((A) > (B) ? (A) : (B)) #define square(x) x * x int main() {int i = 0;int j = 1;int x = 5;printf("%d\n", max(i++, j++));printf("%d\n", i);printf("%d\n", j);printf("%d\n", square(x + 1));return 0; }
程序输出为2 1 3 11。.因为max(i++,j++)被替换成了(i++) > (j++) ? (i++) : (j++),所以大的数字j自增了两次。
最后并没有输出我们理想的答案(5 + 1) * (5 + 1),因为squre(x + 1)被替换为了:x + 1 * x + 1
所以:
#define square(x) x * x
应该改写成
#define square(x) (x) * (x)
可以通过#undef指令取消名字的宏定义,这样做可以保证后续的调用是函数调用,而不是宏调用:
#undef getchar int getchar(void) {...}
形式参数不能用带引号的字符串替换。但是,如果在替换文本中,参数名以#作为前缀则结果被拓展为由实际参数替换该参数的带引号的字符串。如:
#define dprint(expr) printf(#expr " = %g\n", expr)
使用语句:
dprint(x/y);
调用该宏时,该宏被拓展为:
printf("x/y"" = %g\n",x/y);
为了防止一个源文件重复包含一个头文件,可以采用条件包含的方法。
如:
#if !defined(HDR) #define HDR /* hdr.h文件的内容放在这里*/ #endif
等价为:
#ifndef HDR #define HDR /* hdr.h文件的内容放在这里*/ #endif
下面的这段预处理代码首先测试系统变量SYSTEM,然后根据该变量的值确定包含哪个版本的头文件:
#if SYSTEM == SYSV#define HDR "sysv.h" #elif SYSTEM == BSD#define HDR "bsd.h" #elif SYSTEM ==MSDOS#define HDR "msdos.h" #else#define HDR "default.h" #endif #include HDR
更多推荐
C程序设计语言读书笔记(4)
发布评论