C程序设计语言 第2版
《The C Programming Language》
封面如下,选取书中知识点用以记录学习。
第1章 导言
1.1 入门
- 源程序 test.c;
- 编译 test.obj
- 连接 test.exe
C语言程序中,
- 函数:包含语句,指定要执行的计算操作。
- 变量:存储计算过程中使用的值。
每个程序都以 main 函数的起点开始执行。
构成 C 程序的基本单位是函数。
1.2 变量与算术表达式
所有变量都必须声明后使用。
声明 declaration:说明每个标识符的含义,不需要预留存储空间。
定义 definition:预留存储空间的声明,创建变量或分配存储单元。
舍位:整数除法,结果中任何小数位都会被舍弃。 5/9 = 0
华氏、摄氏对照公式:℃ = (5/9) (℉-32)
#include <stdio.h>
// 当 fahr= 0,20, ... ,300 时,打印华氏温度与摄氏温度对照表
int main()
{
float fahr, celsius;
int lower, upper, step;
lower = 0; // 温度表的下限
upper = 300; // 温度表的上限
step = 20; // 步长
fahr = lower;
printf("Fahr Celsius\n");
while(fahr <= upper)
{
celsius = (5.0/9.0)*(fahr-32);
printf("%3.0f\t%6.1f\n", fahr, celsius);
fahr = fahr + step;
}
return 0;
}
%6.2f:按浮点打印,至少6个字符宽,小数点后两位小数。
1.3 for语句
判别式为真,则执行循环体。
适合初始化和增长步长都是单条语句并且逻辑相关的情形。
#include <stdio.h>
// 当 fahr= 0,20, ... ,300 时,打印华氏温度与摄氏温度对照表
int main()
{
float fahr;
printf("Fahr Celsius\n");
for(fahr=0; fahr <= 300; fahr = fahr+20)
printf("%3.0f %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
return 0;
}
1.4 符号常量
define LOWER 0 //末尾没有分号!
1.5 字符输入输出
c = getchar();//从文本流中读入下一个输入字符
putchar(c);//打印一个字符
1.5.1 文件复制
#include <stdio.h>
// 版本2:按字符将输入复制到输出
int main()
{
int c;
while((c = getchar())!= EOF) //end of file,文件结束符
putchar(c);
return 0;
}
这里将 c 声明成 int ,因为 c 必须足够大,除了存储字符,还要存储 EOF。(EOF在<stdio.h>中是整型)
1.5.2 字符计数
for(nc=0; getchar() != EOF; ++nc); //空语句
1.5.3 行计数
while((c=getchar() != EOF))
if(c=='\n')
++nl;
1.5.4 单词计数(不包括空格、制表符或换行符的字符序列)
#include <stdio.h>
#define IN 1
#define OUT 0
// 版本1:利用state标志位
int main()
{
int c, nl, nw, nc, state;
state = OUT; //state不在单词中
nl = nw = nc = 0; //line, word, char
while((c = getchar())!= EOF)
{
++nc; // 字符+1
if(c == '\n')
++nl; // 行数+1
if(c == ' ' || c == '\n' || c == '\t')
state = OUT; //单词外
else if(state == OUT) //非空格且单词外
{
state = IN; //改单词内
++nw; //单词+1
}
}
printf("nl=%d, nw=%d, nc=%d\n", nl, nw, nc);23
return 0;
}
// 版本2:利用上一个字符跟本字符一起比较
int main()
{
int c, nw=0, lastc = ' ';
while((c = getchar())!=EOF)
{
if(lastc == ' ' && c != ' ')
nw++;
lastc = c;
}
printf("单词数: %d\n", nw);
return 0;
}
1.6 数组
/* 统计各个数字、空白符及其他字符个数*/
nwhite = nother = 0; //空白符个数,其他字符个数
for(i=0; i<10; ++i)
ndigit[i] = 0; //数组存放各个数字出现的次数
while((c = getchar()) != EOF)
if(c>='0' && c>='9')
++ndigit[c-'0'];
else if(c==' ' || c=='\t' || c=='\n')
++nwhite;
else
++nother;
1.7 函数
同一函数不能分割存放在多个文件中。
形参:函数定义中圆括号内列表中出现的变量。
实参:函数调用中与形参对应的值。
函数不一定都有返回值,而main末尾有 return,可以向其调用者(程序的执行环境)返回一个值。
- 返回值为0,正常终止;
- 非零,出现异常情况或出错结束条件。
函数原型(声明):int power(int m, int n);
它必须与 power 函数的定义和用法一致。
函数原型与函数声明中参数名不要求相同,也可写成:int power(int, int);
1.8 参数——传值调用
-
值传递:传递给被调函数的参数值存放在临时变量(本地副本)中,而不是存放在原来的变量中。
被调函数不能直接修改主调函数中变量的值,只能修改其私有的临时副本的值。
-
指针:指向变量的地址。
调用者向被调函数提供待设置值的地址,可以让函数修改主调函数中的变量
-
数组参数:数组名作为参数时,传递给函数的值是数组起始元素的位置或地址 —— 并不复制数组本身。
1.9 字符数组
当C语言程序中出现类似hello\n
的字符常量时,将以字符数组的形式存储。数组的各元素分别存储字符串的各个字符,并以\0
标志字符串的结束。
/* 程序读入一组文本行,并把最长的文本行打印出来 */
#include <stdio.h>
#define MAXLINE 1000 //允许的输入行最长长度
int getLine(char line[], int maxline); // 将一行读入line,返回长度
void copy(char to[], char from[]); // from复制到to
int main()
{
int len; // 当前行长度
int max; // 目前为止最长行的长度
char line[MAXLINE];
char longest[MAXLINE];
max = 0;
while((len = getLine(line, MAXLINE)) > 0) //行不为空,则拿下
{
if(len > max) //拿到最长行给longest
{
max = len;
copy(longest, line);
}
}
if(max > 0)
printf("%s", longest); //最后输出最长行。这里longest是自带换行符的
return 0;
}
int getLine(char line[], int maxline)
{
int c, i;
// 不超过行最长长度,不到EOF,不到换行符,要同时成立
for(i=0; i<maxline-1 && (c=getchar())!=EOF && c!='\n'; ++i)
{
line[i] = c;
}
if(c == '\n') //如果是因为\n 而结束,说明是一行,\n 加到字符串末尾
{
line[i] = c;
++i;
}
line[i] = '\0'; //字符串结尾
return i;
}
void copy(char to[], char from[])
{
int i = 0;
while((to[i] = from[i]) != '\0')
++i;
}
1.10 外部变量与作用域
局部变量、自动变量 auto、私有变量 保存在栈中
- 只在函数被调用时分配存储单元,执行完毕退出时消失。
- 在函数的两次调用之间,自动变量不保留前次调用时的赋值。
- 每次进入函数时都要显示为其赋值。
- 如果没有赋值则其中存放的是无效值。
外部变量 extern
- 所有函数都可通过变量名来访问,因此可以用来在函数间交换数据而不使用参数表。
- 程序执行期间一直存在,即使再对外部变量赋值的函数返回后,这些变量仍保持原来的值不变。
- 定义在所有函数之外,且只能定义一次,定义后编译程序将为它分配存储单元。
- 在使用外部变量的函数中,必须声明相应的外部变量。
extern int max;
1.若外部变量定义在使用它的函数之前,可以省略extern声明;
2.若变量在 file1 中定义,在 file2 和 file3 中使用,那么 file2 和 file3 必须声明来建立该变量与其定义之间的联系。
3.通常把变量和函数的 extern 声明放在一个单独的文件中 → 头文件
静态变量 static
- 限定的外部变量和函数,其后的对象的作用域限定为被编译源文件的剩余部分,可以达到隐藏外部对象的目的。
- 声明内部变量,只能在特定函数中使用,但一直占据存储空间的变量。赋值一次,多次函数调用之间保持值不变。
- 静态变量只在第一次进入程序块时被初始化一次。
寄存器变量 register
- 告诉编译器,变量在程序中使用频率较高。
- 思想:变量放机器寄存器中,使程序更小、执行速度更快,编译器直接忽略。
- 只适用于 auto 变量和函数的形参。
- 寄存器变量的地址不可访问。(没有内存位置,不能用 &)
C语言编译后,将内存分为以下几个区域:
-
栈(stack):由编译器进行管理,自动分配和释放,存放函数调用过程中各种参数、局部变量、返回值以及返回地址。
-
堆(heap):用于程序动态申请分配和释放空间。(malloc, free)
正常情况下,申请的控件在使用结束后应该释放,若程序员未释放,则程序结束时系统自动回收。(不是数据结构中的“堆”)
-
全局(静态)存储区:分为 DATA 段和 BSS 段
DATA 段(全局初始化区),存放初始化的全局变量和静态变量;
BSS 段(全局未初始化区),存放未初始化的全局变量和静态变量。
-
文字常量区:存放常量字符串,程序结束后由系统释放。
-
程序代码区:存放程序的二进制代码。
附录
电子书链接:https://pan.baidu.com/s/1xNX9Exu_2msDeTtWgRbiwQ
提取码:irsd