C Primer Plus
数据类型
基本类型:
- int
- char
- float
- double
类型修饰符:
- long
- short
- unsigned
- signed
其他:
- void
- _Bool
- _Complex 复数
- _Imaginary 虚数
在计算机中存储这些数据类型之分两种:整数类型(integer),浮点数类型(floating-point)
整数就是由一个二进制数,浮点数分为小数部分和指数部分,分别存储。
位,字节,字
位:bit,一个比特,存0 or 1
字节:byte,一个字节,存8个bit
字:word,自然存储单位,你多少位的系统,一个word就代表多少位,对于32位系统,就是32bit,对于64位系统就是64bit。
int类型
不同的整型的差别在于,存储数值的范围(long,short)以及是否有符号(unsigned,signed)
int的取值范围依赖计算机系统,int存储在计算机中的一个字word中,多少位的系统,int就是2的多少次方。
例如:16位系统,2^16=65536 , 如果不带符号(unsigned int),取值范围就是0<int<65535 ; 如果带符号的int(用掉了最高位作为符号位),取值范围就是-32768<int<32767
各种修饰后的int:
#include<stdio.h>
#include<string.h>
#include<time.h>
void main() {
int i1 ;
printf("%d\n",sizeof(i1));
short int i2;
printf("%d\n",sizeof(i2));
long int i3;
printf("%d\n",sizeof(i3));
long long int i4;
printf("%d\n",sizeof(i4));
unsigned int i5;
printf("%d\n",sizeof(i5));
}
//ubunto14.04中的输出
/*
4
2
4
8
4
*/
long和short可能占用比int类型更多或者更少的内存,这样做是为了适应不同的机器。
一般来讲:short = 2byte ,long=4byte , long long = 64byte。
而int则由操作系统决定。
32位可以表示:-2147483648~2147483647
long常量和long long常量
对于一个常量,编译器首先用int类型存储,不够则往上unsigned int , long , unsigned long , long long , unsigned long long 。
如果希望明确用long,long long ,unsigned long long 来存储常量,则可以在常量后面添加字符,L , LL , uLL ,(无视大小写,但建议使用L,不要用小写的l,因为l跟1很像。)
printf , 打印 short int 用 %hd , 打印long int 用%ld。
char类型
char在技术实现上就是int,char中存的是代码字符的对应ASCII码。char的大小一般为1byte。
如果不是用ASCII码,则有所不同,char可能是2Byte,或者4byte
单引号 ’ 代表字符,双引号 " 代表字符串。
float , double , long double类型
float(单精度浮点数)至少能表示6位有效数字 ,范围是10-37~1037,一般为32位
double(双精度浮点数)至少能表示10位有效数字,一般为64位。
long double C只保证long double 至少同double类型一样精确。
浮点数的存储方式:
以IEEE R32.24 , IEEE R64.53标准来看:
float:(从高位到低位)
- 符号位:1位
- 指数位:8位
- 尾数:23位
double:(从高位到低位)
- 符号位:1位
- 指数位:11位
- 尾数:52位
默认情况下,编译器会将浮点常量当做double类型。
所以可以在数字后面加f或F来告诉编译器,此浮点常量用float存储。l或者L来告诉编译器,此浮点常量用long double来存储。
复数和虚数类型
float _Complex , double _Complex , long double _Complex
float _Imaginary , double _Imaginary , long double _Imaginary
complex.h头文件,可以用I (大写的i) 表示-1的平方根。
字符串格式化输入/输出
C语言用\0,空字符来标记字符串的结束。其ASCII码值为0
数组是同一类型的数据元素的有序序列。
scanf当遇到空白字符空格(blank),制表符(tab),换行符(newline)处,停止读取。而gets()函数可以处理一般的字符串。
字符串与字符:
“x” = [‘x’,’\0’] , ‘x’ = ‘x’ ;
strlen()函数
sizeof,可以知道某个变量定义占用了多少个内存单元。
strlen(), 当识别到空字符‘\0’时,就停止计数。
例如:
#include<stdio.h>
#include<string.h>
#define strdefine = "hello life!"
void main() {
char str[40] = "aaa bbb ccc";
printf("strlen:%d \n",strlen(str));
printf("sizeof:%d \n",sizeof(str));
printf("strlen:%d \n",strlen(strdefine));
printf("sizeof:%d \n",sizeof(strdefine));
}
//输出,11,40,11,12
//sizeof是指申请了多少内存来存,就返回多少,strlen就只关心\0在哪里,发现了就返回\0前面的字符长度。
常量与C预处理器
用define语句创建常量,在编译时,会在对应的位置完成替换。
const修饰符创建常量,比较灵活,把变量的声明转换为常量的声明,但是不可以被修改。
研究与利用printf()和scanf()。
82页有详细说明。
此处强调一下转换说明的意义:
在计算机中,所有数据类型都是用二进制数进行存储的,转换说明,其实就是翻译,把机器码翻译成不同的数据类型,并且打印出来。
循环,条件,运算符等基本概念介绍。
while,for,if,+,-等符号。
I/O函数,getchar() , putchar(), 比 scanf() , printf()函数更快,而且更简洁。但是getchar和putchar只能捕捉一个char,需要用循环配合才能一直捕捉字符。
字符输入/输出和输入确认
缓冲区存在的意义:若干个字符作为一个块传输 faster than 逐个字符发送,错了还能改。
缓冲分两类:完全缓冲(fully buffered) , 行缓冲(line-buffered)。
- 完全缓冲: 缓冲区满了就清空,内容发送到目的地
- 行缓冲:遇到一个换行符时就清空,内容发送到目的地
ANSI C指定应该对输入进行缓冲。
EOF:end of file
[Ctrl+Z] : 是模拟的EOF,等待的输入函数遇到时,就会认为输入结束。
输入重定向运算符:<
输出重定向运算符:>
echo_eof < file.txt
//上诉语句的意思是,把file.txt文件与stdin流关联起来,echo_eof程序中,等待用户输入的地方,就会由file.txt文件的内容代替。
echo_eof > new_file.txt
//将stdout重定向到new_file.txt文件中。
指针与数组
对于多维数组:
arr[4] [2] 的存储结构如下:
arr[0][0] arr[0][1] arr[1][0] arr[1][1] arr[2][0] arr[2][1] arr[3][0] arr[3][1]
//如果用指针p去指向arr[0],那么*p读取的值,其实是
arr[0][0] arr[0][1]
//因为arr[0],是包含arr[0][0] arr[0][1]的地址块,在算sizeof的时候,就是两个数组元素的大小。,指针+1当然跳转的地址也是两个数组元素,他会跳到arr[1]的地方。也就是:
arr[1][0] arr[1][1]
存储类、链接和内存管理
存储类说明符:auto,register , static , extern , typedef
内存管理:静态内存(全局变量),自动内存(某个函数的局部变量),分配内存(malloc ,free)
文件输入/输出
使用getc,putc来获得文件中的字符。
fprintf,fscanf,fgets,fputs,与之前谈到的没有带f的函数使用类似,但是这里的第一个函数要是文件。
“a+”模式,可以对文件进行读写。
rewind(fp) 命令,可以使程序回到文件开始处。
fgets(buf,MAX,fp),读到第一行换行字符,比最大字符串少一个字符,或者读到EOF。
fseek() 移动到具体位置
ftell() 返回文件当前位置
fgetpos(),fsetpos() 读大文件的文件位置。
结构和其他数据形式
讲述了结构,枚举,联合,函数指针的一些操作。
位操作
主要讲述一些位操作,位反(~),位与(&),位或(|),位异或(^),左移(<<),右移(>>)
C预处理器和C库
#define , #include , #undef ,#ifdef , #ifndef , #if ,#elif ,#else,#endif
不常用的#line , #error , #progma
内联函数,用inline声明,与宏定义类似,是把函数调用,直接变成函数体替换。
C库:
io库:stdin.h
数学库:math.h
通用工具库:stdlib.h 。 qsort()函数,快速排序。
诊断库:assert.h
字符串库: string.h, :memcpy()假定两个内存区域之间没有重叠 , memmove()则不作这个假定,
可变参数:stdarg.h :
高级数据表示
链表,抽象数据类型,接口实现,二叉树。