文章目录
- 第一章初识C语言
-
-
-
- 1.6 语言标准
- 1.8 编程机制
-
-
- 第2章 C语言概述
-
-
-
- 2.2 语言风格
- 2.7 调试程序
- 2.8 关键字和保留标识符
-
-
- 第3章 数据和C
-
-
-
- 3.1 程序讲解
- 3.3 关键字的数据类型
- 3.4 C语言基础数据类型
- 3.5 使用数据类型
- 3.7 转换序列示例
-
-
- 第4章 字符串和格式化输入/输出
-
-
-
- 4.1 前导程序
- 4.2 字符串
- 4.3 常量和C预处理器
- 4.4 printf()和scanf()
-
-
- 第5章 操作符、表达式和句子
- 第6章 C控制句:循环
-
-
-
- 6.3 使用关系运算符和表达式
-
-
- 第7章 C控制句:分支和跳转
-
-
-
- 7.2 if else语句
-
-
第一章初识C语言
1.6 语言标准
美国国家标准协会(ANSI)1983年成立了一个委员会(X3J11)开发了一套新标准,并于1989年正式公布。这个标准(ANSI C)C语言和C标准库的定义。1990年,国际标准化组织采用了这套C标准(ISO C)。ISO C和ANSI C标准完全相同。ANSI/ISO标准的最终版本通常叫作C89(因为ANSI 于 1989 或者C90(因为ISO该标准于1990年批准)。此外,由于ANSI首先公布C标准,因此业内人士通常使用C标准 ANSI C。
1994年,ANSI/ISO联合委员会(C9X委员会)开始修改C标准,最终发布C99标准。实现的新目标:
- 一是支持国际编程。例如,提供多种处理国际字符集的方法。
- 第二,弥补缺陷。在C移动到64位处理器时,添加标准。
- 第三,适应科学和工程项目中的关键值计算,提高C的适应性。
2007年,标准委员会承诺C标准的下一个版本是C1X,2011年终于发布了C11标准。出于对当前编程安全的担忧,信任程序员的目标没有得到很好的接受和支持。C99,使得C99的一些特征已经成为C11可选项。新标准增加了支持当前使用多处理器的计算机的可选项。
1.8 编程机制
GUN该项目始于1987年,开发了大量自由UNIX软件的集合(GUN的意思是“GUN’s Not UNIX”,即GUN不是UNIX)。GUN编译器集合(也称为编译器集合(也称为编译器集合(也称为编译器集合(也称为编译器集合)(也称为编译器集合(也称为编译器集合)(也称为编译器集合)(也称为编译器集合)GCC,其中包含GCC C编译器)是该项目的产品之一。gcc可以调用命令GCC C编译器。很多用途gcc的系统都用cc作为gcc的别名。
LLVM项目成为cc另一个替代品。该项目是伊利诺大学2000年开始的开源软件集合。ClangC代码可以通过编译器处理clang调用。
GUN和LLVM都可以用-v所以每个系统都使用选项来显示版本信息cc别名来代替gcc或clang下列组合:
cc -v
显示您使用的编译器及其版本。 gcc和clang不同的C标准可以根据不同版本选择操作选项。
gcc -std=c99 inform.c gcc -std=c1x inform.c gcc -std=c11 inform.c
第一行调用C第二行调用99标准GCC接受C11前草案标准,第三行调用GCC接受的C11标准版本。Clang在这一点上,编译器的用法和用法GCC相同。
第2章 C语言概述
2.2 语言风格
C99和C11允许使用更长的标识符名,但编译器只识别前63个字符。外部标识符只允许31个字符。
操作系统和C库通常使用从一个或两个下划线字符开始的标识符(例如,_kcab),所以最好避免在你自己的程序中使用这个名字。标准标签从一个或两个下划线字符开始,如图书馆标识字符。保留了这样的标志符。
C99之前的标准要求将声明放在块的顶部,其优点是将声明放在一起更容易理解程序的用途。C99允许在需要时声明变量。这样做的好处是,在给变量赋值之前,不要忘记给变量赋值。
**函数调用语句:**多年来,C标准中从未有函数调用句!值得一提的是,函数调用本身是一种表达式,圆括号是一个操作符,圆括号左侧的函数名是操作对象。C11标准中,这样的表达式是一种后缀表达式。在表达式末尾加上分号,就成了表达式语句。
2.7 调试程序
:将有效的C符号放在错误的地方,不遵守C语言的规则就会犯语法错误。
:若遵循C规则,但结果不正确,则犯语义错误。例如,编译器无法检测到逻辑错误。
2.8 关键字和保留标识符
ISO C关键字:
C90 | C99 | C11 | |||
---|---|---|---|---|---|
auto | extern | short | const | _Alignas | _Thread_local |
break | float | sizeof | enum | _Alignof | |
ase | for | static | signed | _Atomic | |
continue | goto | struct | void | _Bool | |
default | if | switch | volatile | _Complex | |
do | inline | typedef | _Generic | ||
double | int | union | _Imaginary | ||
else | long | _Noreturn | |||
while | unsigned | _Static_assert |
保留标识符包括那些以下划线字符开头的标识符和标准库函数名,如printf()。
第3章 数据和C
3.1 程序讲解
printf("%f", num) // 打印浮点值
printf("%.2f", num) // .2用于精确控制输出小数点后两位
3.3 数据类型关键字
C语言的数据类型关键字:
最初K&R给出的关键字 | C90标准添加的关键字 | C99标准添加的关键字 |
---|---|---|
int | signed | _Bool |
long | void | _Complex |
short | _Imaginary | |
unsigned | ||
char | ||
float | ||
double |
按计算机的存储方式可分为两大基本类型:整数类型和浮点数类型。
3.4 C语言基本数据类型
0x或0X前缀表示十六进制值,0前缀表示八进制。
以十进制显示数字,使用%d;以八进制显示数字,使用%o;以十六进制显示数字,使用%x。另外,要显示各进制数的前缀0、0x和0X,必须分别使用%#o、%#x、%#X。
short :16位
int:16位或32位
long:32位;要把一个较小的常量作为long类型对待,可以在值的末尾加上l(小写的L)或L后缀。l或L后缀也可用于八进制和十六进制整数,如020L和0x10L。
long long :64位;使用ll或LL后缀来表示long long类型的值,如3LL。另外,u或U后缀表示unsigned long long,如5ull、10LLU、6LLU或9Ull。
C语言提供3个附属关键字修饰基本整数类型:short、long、signed和unsigned。
打印unsigned int类型的值,使用%u转换说明;打印long类型的值,使用%ld转换说明。在x和o前面可以使用l前缀,%lx表示以十六进制格式打印long类型整数,%lo表示以八进制格式打印long类型整数。虽然C允许使用大写或小写的常量后缀,但是在转换说明中只能使用小写。
对于short类型,可以使用h前缀。%hd表示以十进制显示short类型的整数,%ho表示以八进制显示。h和l前缀都可以和u一起使用,用于表示无符号类型。例如,%lu表示打印unsigned long类型的值,%lld和%llu分别表示long long的有符号和无符号类型。
unsigned int un = 3000000000;
short end = 200;
long big = 65537;
long long verybig = 12345678908642;
printf("un = %u and not %d\n", un, un); // un = 3000000000 and not -1294967296
printf("end = %hd and %d\n", end, end); // end = 200 and 200
printf("big = %ld and not %hd\n", big, big); // big = 65537 and not 1
printf("verybig = %lld and not %ld\n", verybig, verybig); // verybig = 12345678908642 and not 1942899938
非打印字符:
单引号只适用于字符、数字和标点符号,有些ASCII字符打印不出来。
第1种方法是使用ASCII码:char beepc = 7;
第2种方法是使用转义序列:char nerf = '\n';
转义序列 | 含义 |
---|---|
\a | 警报,C标准规定警报字符不得改变活跃位置 |
\b | 退格 |
\f | 换页,将活跃位置移至下一页的开始处 |
\n | 换行,把活跃位置移至下一行的开始处 |
\r | 回车,把活跃位置移至当前行的开始处 |
\t | 水平制表符,把活跃位置移至下一个水平制表点(常是第1、9、17、25个等字符位置) |
\v | 垂直制表符,把活跃位置移至下一个垂直制表点 |
\\ | 反斜杠(\) |
\’ | 单引号 |
\" | 双引号 |
\? | 问号 |
\0oo | 八进制值(oo必须是有效的八进制数,即每个o可表示0~7中的一个数) |
\xhh | 十六进制值(hh必须是有效的十六进制数,即每个h可表示0~f中的一个数) |
活跃位置:显示设备(屏幕、电传打字机、打印机等)中下一个字符将出现的位置。简而言之,屏幕光标位置就是活跃位置。
这些转义序列字符不一定在所有显示设备上都起作用。例如,换页符和垂直制表符在PC屏幕上会生成奇怪的符号,光标并不会移动。只有将其输出到打印机上时才会产生前面描述的效果。
打印字符:
printf()函数用%c指明待打印的字符。printf()函数中的转换说明决定了数据的显示方式,而不是数据的存储方式。
精确宽度整数类型(可选项):int32_t
表示整数类型的宽度正好是32位。
最小宽度类型:至少有指定宽度的最小整数类型。例如,int_least8_t
是可容纳8位有符号整数的类型中宽度最小的类型的一个别名。
最快最小宽度类型:一组可使计算达到最快的类型集合。例如,int_fast8_t
被定义为系统中对8位有符号值而言运算最快的整数类型的别名。
最大整数类型:intmax_t
为最大的有符号整数类型,uintmax_t
表示最大的无符号整数类型。
printf()打印特定类型时要求与相应的转换说明匹配。inttypes.h头文件提供了一些字符串宏来显示可移植类型。例如,PRId32
字符串宏,代表打印32位有符号值的合适转换说明
printf("me32 = %" PRId32 "\n", me32);
浮点型常量:
-1.56E+12
2.87e-3
3.14159
.2
4e16
.8E-5
100.
默认情况下,编译器假定浮点型常量是double类型的精度。
在浮点数后面加上f或F后缀可覆盖默认设置,编译器会将浮点型常量看作float类型,如2.3f和9.11E9F。使用l或L后缀使得数字成为long double类型,如54.3l和4.32L。没有后缀的浮点型常量是double类型。
C99标准添加了十六进制表示浮点型常量,即在十六进制数前加上十六进制前缀(0x或0X),用p和P分别代替e和E,用2的幂代替10的幂(即,p计数法)。0xa.1fp10
打印浮点值:
printf()函数使用%f转换说明打印十进制计数法的float和double类型浮点数,用%e打印指数计数法的浮点数。如果系统支持十六进制格式的浮点数,可用a和A分别代替e和E。打印long double类型要使用%Lf、%Le或%La转换说明。给那些未在函数原型中显式说明参数类型的函数(如,printf())传递参数时,C编译器会把float类型的值自动转换成double类型。
还有另外一个特殊的浮点值NaN(not a number),表示函数的行为是未定义的,例如超出定义域。
3种复数类型:float _Complex、double _Complex、long double _Complex,例如,float _Complex类型的变量应包含两个float类型的值,分别表示复数的实部和虚部。
3种虚数类型:float _Imaginary、double _Imaginary、long double _Imaginary
如果包含complex.h头文件,便可用complex代替_Complex,用imaginary代替_Imaginary,还可以用I代替-1的平方根。
sizeof是C语言的内置运算符,以字节为单位给出指定类型的大小。C99和C11提供%zd转换说明匹配sizeof的返回类型(即size_t类型)。一些不支持C99和C11的编译器可用%u或%lu代替%zd。
3.5 使用数据类型
int cost = 12.99; // 用double类型的值初始化int类型的变量
float pi = 3.1415926536; // 用double类型的值初始化float类型的变量
第1个声明,cost的值是12。C编译器把浮点数转换成整数时,会直接丢弃(截断)小数部分,而不进行四舍五入。
第2个声明会损失一些精度,因为C只保证了float类型前6位的精度
printf()和scanf()函数与一般函数不同,它们的参数个数是可变的。printf()和scanf()函数用第1个参数表明后续有多少个参数。
注意,用%d显示float类型的值,其值不会被转换成int类型。
3.7 转义序列示例
最初,prinf()语句把输出发送到缓冲区的中间存储区域,然后缓冲区中的内容再不断被发送到屏幕上。C标准明确规定了何时把缓冲区中的内容发送到屏幕:当缓冲区满、遇到换行字符或需要输入的时候(从缓冲区把数据发送到屏幕或文件被称为刷新缓冲区)。
还有一种刷新缓冲区的方法是使用fflush()函数。
第4章 字符串和格式化输入/输出
4.1 前导程序
char name[40]; // name是一个可容纳40个字符的数组
scanf("%s", name); // 这里的name本身是一个地址
4.2 字符串
字符串数组末尾位置的字符\0是空字符,C语言用它标记字符串的结束,它是非打印字符(其ASCII码值为0)。C中的字符串一定以空字符结束,这意味着数组的容量必须至少比待存储字符串中的字符数多1。因此,40个存储单元的字符串,只能存储39个字符,剩下一个字节留给空字符。
一般而言,根据%s转换说明,scanf()只会读取字符串中的一个单词,而不是一整句,在它遇到第1个空白(空格、制表符或换行符)时就不再读取输入。C语言还有如fgets()这样的输入函数用于读取一般字符串。
"x"和’x’实际并不一样,"x"是派生类(char数组==“x \0”),'x’是基本类型(char)。
strlen()给出字符串中字符长度(包括空格和标点符号,不包含末尾不可见空字符),其被包含在string.h
头文件中,返回类型同sizeof()函数。
4.3 常量和C预处理器
符号常量的创建方法:
/* 1. */
float taxrate;
taxrate = 0.015;
/** 2.C预处理器 * 将在编译时替换,这样定义的常量也称为明示常量 */
#define TAXRATE 0.015
C90标准新增了const关键字,用于限定一个变量为只读。
C头文件limits.h和float.h分别提供了与整数类型和浮点类型大小限制相关的详细信息。每个头文件都定义了一系列供实现使用的明示常量。例如,limits.h头文件包含以下类似的代码:
#define INT_MAX +32767
#define INT_MIN -32768
明示常量 | 含义 |
---|---|
CHAR_BIT | char类型的位数 |
CHAR_MAX | char类型的最大值 |
CHAR_MIN | char类型的最小值 |
SCHAR_MAX | signed char类型的最大值 |
SCHAR_MIN | signed char类型的最小值 |
UCHAR_MAX | unsigned char类型的最大值 |
SHRT_MAX | short类型的最大值 |
SHRT_MIN | short类型的最小值 |
USHRT_MAX | unsigned short类型的最大值 |
INT_MAX | int类型的最大值 |
INT_MIN | int类型的最小值 |
UINT_MAX | unsigned int类型的最大值 |
LONG_MAX | long类型的最大值 |
LONG_MIN | long类型的最小值 |
ULONG_MAX | unsigned long类型的最大值 |
LLONG_MAX | long long类型的最大值 |
LLONG_MIN | long long类型的最小值 |
ULLONG_MAX | unsigned long long类型的最大值 |
类似地,float.h头文件中也定义了一些明示常量,如FLT_DIG和DBL_DIG,分别表示float类型和double类型地有效数字位数。
明示常量 | 含义 |
---|---|
FLT_MANT_DIG | float类型的尾数位数 |
FLT_DIG | float类型的最少有效数字位数(十进制) |
FLT_MIN_10_EXP | 带全部有效数字的float类型的最小负指数(以10为底) |
FLT_MAX_10_EXP | float类型的最大正指数(以10为底) |
FLT_MIN | 保留全部精度的float类型最小正数 |
FLT_MAX | float类型的最大正数 |
FLT_EPSILON | 1.00和比1.00大的最小float类型值之间的差值 |
表中所列都与float类型相关,把明示常量名中的FLT分别替换成DBL和LDBL,即可分别表示double和long double类型对应的明示常量。
4.4 printf()和scanf()
转换说明 | 输出 |
---|---|
%a、%A | 浮点数、十六进制数和p记数法(C99/C11) |
%c | 单个字符 |
%d、%i | 有符号十进制整数 |
%e、%E | 浮点数,e记数法 |
%f | 浮点数,十进制记数法 |
%g、%G | 根据值的不同,自动选择%f或%e(%E)。%e(%E)格式用于指数小于-4或者大于等于精度时 |
%o | 无符号八进制整数 |
%p | 指针 |
%s | 字符串 |
%u | 无符号十进制整数 |
%x、%X | 无符号十六进制整数,使用十六进制数0f、0F |
%% | 打印一个百分号 |
prinf(格式字符串, 待打印项1, 待打印项2, …);
格式字符串包含两种形式不同的信息:
-
实际要打印的字符;
-
转换说明。
修饰符 | 含义 |
---|---|
标记 | 5种标记(-、+、空格、#和0),可以不使用标记或使用多个标记示例:“%-10d” |
数字 | 最小字段宽度如果该字段不能容纳待打印的数字或字符串,系统会使用更宽的字段示例:“%4d” |
. 数字 | 精度对于%e、%E、%f转换,表示小数点右边数字的位数对于%g和%G转换,表示有效数字最大位数对于%s转换,表示待打印字符的最大数量对于整型转换,表示待打印数字的最小位数如有必要,使用前导0来达到在这个位数只使用 . 表示其后跟随一个0,所以%.f和%.0f相同示例:"%5.2f"打印一个浮点数,字段宽度为5字符,其中小数点后有两位数字 |
h | 和整型转换一起使用,表示short int或unsigned short int类型的值示例:“%hu”、“%hx”、“%6.4hd” |
hh | 和整型转换说明一起使用,表示signed char或unsigned char类型的值示例:“%hhu”、“%hhx”、“%6.4hhd” |
j | 和整型转换说明一起使用,表示intmax_t或uintmax_t类型的值。这些类型定义在stdint.h中示例:“%jd”、“%8jx” |
l | 和整型转换说明一起使用,表示long int或unsigned long int类型的值示例:“%ld”、“%8lu” |
ll | 和整型转换说明一起使用,表示long long int或unsigned long long int类型的值示例:“%lld”、“%8llu” |
L | 和浮点转换说明一起使用,表示long double类型的值示例:“%Lf”、“%10.4Le” |
t | 和整型转换说明一起使用,表示ptrdiff_t类型的值。ptrdiff_t是两个指针差值的类型(C99)示例:“%td”、“%12ti” |
z | 和整型转换说明一起使用,表示size_t类型的值。size_t是sizeof返回的类型(C99)示例:“%zd”、“%12zd” |
注意 float参数的转换:
。。。72
标记 | 含义 |
---|---|
- | 待打印项左对齐。即,从字段的左侧开始打印该项示例:“%-20s” |
+ | 有符号值若为正,则在值前面显示加号;若为负,则在值前面显示减号示例:“%+6.2f” |
空格 | 有符号值若为正,则在值前面显示前导空格(不显示任何符号);若为负,则在值前面显示减号+标记并覆盖空格示例:“% 6.2f” |
# | 把结果转换为另一种形式。如果是%o格式,则以0开始;如果是%x或%X格式,则以0x或0X开始;对于所有的浮点格式,#保证了即使后面没有任何数字,也打印一个小数点字符。对于%g和%G格式,#防止结果后面的0被删除示例:“%#o”、“%#8.0f”、“%+#10.3e” |
0 | 对于数值格式,用前导0代替空格填充字段宽度。对于整数格式,如果出现-标记或指定精度,则忽略该标记示例:“%010d"和”%08.3f" |
参数传递:计算机根据变量类型(不是根据转换说明)把转入的参数值放入栈中,printf()函数则根据转换说明(不是根据变量类型)从栈中读取值。
rv = printf(...);
的返回值计算针对所有字符数,包括空格和不可见的换行符(\n)。
打印较长字符串:
- 使用反斜杠(\)和Enter键组合来断行。
- ANSI C引入的字符串连接。在两个用引号括起来的字符串之间用空白隔开,C编译器会把多个字符串看作是一个字符串。
- 如果用scanf()读取基本变量类型的值,在变量名前加上一个&;
- 如果用scanf()把字符串读入字符数组中,不要使用&。
scanf()函数使用空白(换行符、制表符和空格)把输入分成多个字段。在依次把转换说明和字段匹配时跳过空白。只要在每个输入项之间输入至少一个换行符、空格或制表符即可,可以在一行或多行输入。唯一例外的是%c转换说明。根据%c,scanf()会读取每个字符,包括空白。
修饰符 | 含义 |
---|---|
* | 抑制赋值示例:“%*d” |
数字 | 最大字段宽度。输入达到最大字段宽度处,或第1次遇到空白字符时停止示例:“%10s” |
hh | 把整数作为signed char或unsigned char类型读取示例:“%hhu”、“%hhd” |
j | 在整型转换说明后面时,表明使用intmax_t或uintmax_t类型示例:“%jd”、“%ju” |
h、l或L | “%hd"和”%hi"表明把对应的值存储为short int类型“%ho”、“%hx"和”%hu"表明把对应的值存储为unsigned short int类型“%ld"和”%li"表明把对应的值存储为long类型“%lo”、“%lx"和”%lu"表明把对应的值存储为unsigned long类型“%le”、“%lf"和”%lg"表明把对应的值存储为double类型在e、f和g前面使用L而不是l,表明把对应的值被存储为long double类型如果没有修饰符,d、i、o和x表明对应的值被存储为int类型,f和g表明把对应的值存储为float类型 |
ll | 把整数作为long long或unisgned long long类型读取示例:“%lld”、“%llu” |
t | 在整型转换说明后面时,表明使用表示两个指针差值的类型(C99)示例:“%td”、“%tx” |
z | 在整型转换说明后面时,表明使用sizeof的返回类型(C99)示例:“%zd”、“%zo” |
第5章 运算符、表达式和语句
第6章 C控制语句:循环
6.3 用关系运算符和表达式比较大小
运算符(优先级从高至低) | 结合律 |
---|---|
() | 从左往右 |
-、+、++、–、sizeof | 从右往左 |
*、/、% | 从左往右 |
+、- | 从左往右 |
<、>、<=、>= | 从左往右 |
==、!= | 从左往右 |
= | 从右往左 |
第7章 C控制语句:分支和跳转
7.2 if else语句
函数名 | 如果是下列参数时,返回值为真 |
---|---|
isalnum() | 字母数字(字母或数字) |
isalpha() | 字母 |
isblank() | 标准的空白字符(空格、水平制表符或换行符)或任何其他本地化指定为空白的字符 |
iscntrl() | 控制字符,如Ctrl+B |
isdigit() | 数字 |
isgraph() | 除空格之外的任意可打印字符 |
islower() | 小写字母 |
isprint() | 可打印字符 |
ispunct() | 标点符号(除空格或字母数字字符以外的任何可打印字符) |
isspace() | 空白字符(空格、换行符、换页符、回车符、垂直制表符、水平制表符或其他本地化定义的字符) |
isupper() | 大写字母 |
isxdigit() | 十六进制数字符 |
函数名 | 行为 |
---|---|
tolower() | 如果参数是大写字符,该函数返回小写字符;否则,返回原始参数 |
toupper() | 如果参数是小写字符,该函数返回大写字符;否则,返回原始参数 |