序言
C语言的6个知识板块:数据,操作符,语句,函数,动态内存分配,程序环境
数据
文本文件和二进制文件
- 不管文本文件还是二进制文件,计算机的存储在物理上都是二进制,按照你所选择的编码方式来解释二进制比特流
- 文本文件:基于字符编码的文件,常见的编码有ASCII编码(1字节)和UNICODE编码(2字节)等
- 二进制文件:所以二进制文件和文本文件的区别不是物理上的,而是逻辑上的,即编码方式的差别。二进制文件可以看做自定义值编码(几个bit表示什么值,由自己决定),所以二进制文件含有一些非标准输出的ASCII码。
- 二进制灵活、存储利用率高但是译码难一些。文本文件的可读性更好
C语言中文本文件和二进制文件的读写差异
- C语言的文本方式读写和二进制方式读写的区别仅仅在于回车换行符的处理上
- 文本读写需要将’n’和’rn’进行转换,二进制读写则不用
文本文件和二进制文件的存储形式
- 5678的存储形式为:ASCII码: 00110101 00110110 00110111 00111000 (四个字节)
- 5678的存储形式为:二进制: 00010110 00101110 (两个字节)
操作符/关键字
typedef-关键字用法
- 为什么使用typedef:给变量创建一个新名字(并不创建新类型);简化一些比较复杂的类型声明
- 用法:
- 变量类型:
- typedef char* pstr;
- pstr mystr;
- mystr放到pstr就是 char* mystr;
- 数组:
- typedef char Line[81];
- Line text;
- text放到Line就是 char text[81];
- 函数/指针:
- typedef dataquelist* portlist;
- portlist plpList;
- plpList放到portlist就是dataquelist* plpList,dataquelist结构体类型的指针
- 变量类型:
struct和typedef struct的区别
- 结构体变量和结构体变量类型
- 结构体变量:
- struct Student
{
int a;
}stu1;
//stu1是一个变量,与struct Student stu1等价
- struct Student
- 结构体变量类型:
- typedef struct Student2
{
int a;
}stu2;
//stu2是一个变量类型,是struct Student(Student是标识符)的新定义,相当于char、int等
- typedef struct Student2
- 结构体变量:
- 结构体变量和结构体变量类型
函数
sprintf()函数
- int sprintf(char str, char format, [argument, …]);
- 根据参数format 字符串来转换并格式化数据,然后将结果复制到参数str所指的字符串数组,直到出现字符串结束(‘\0’)为止
- str:要写入的字符串
- format:格式化字符串
- argument:变量
- 返回值:成功返回字符数(不包括结束符)
- 举例:sprintf(buf, “The ASCII code of a is %d.”, a)
- 用a替换说明符%d,然后将字符串复制到str
- int sprintf(char str, char format, [argument, …]);
文件操作函数头文件
- fopen/fclose函数:stdio.h
- open函数:sys/types.h, sys/stat.h, fcntl.h
- close函数:unistd.h
strlen()函数和sizeof()操作符
- strlen()函数:头文件string.h,只能用地址做参数,运行时计算字符串长度而不是类型占内存的大小。不计入字符串结束符。返回值类型为unsigned int
- sizeof():参数可以是变量也可以是函数,不计字符串
- char str[20]=”0123456789”
- strlen(str) = 10;统计字符串长度,以结束符0x00为字符串结束
- sizeof(str) = 20;统计数组所占内存空间的大小
- char *str = “0123456789”
- sizeof(str) = 4; 指针所占内存空间的大小
- sizeof(*str) = 1; 字符串第一位所占内存
- strlen(str) = 10; 获取字符串长度
- char str[20]=”0123456789”
sizeof()统计字符数组长度
- 字符数组的初始化方式不同,字符数组长度也不同
- 逐个字符赋给数组各元素:char str1[] = {‘I’,’a’,’m’,’h’,’a’,’p’,’p’,’y’};
- 字符串常量初始化字符数组:char str2[] = {“I am happy”} 或”I am happy”;
- “I am happy”相当于{‘I’, ’ ‘, ‘a’, ‘m’, ’ ‘, ‘h’, ‘a’, ‘p’, ‘p’, ‘y’, ‘\0’}
- sizeof(str1) = 8;
- sizeof(str2) = 11;
- 字符数组的初始化方式不同,字符数组长度也不同
字符数组和字符串
- 字符数组char str[100];
- 字符串以’\0’为字符串结束符,系统对字符串常量自动加一个’\0’作为结束符
- 长度为100的字符数组,存储长度为40的字符串,第41个字符为’\0’结束符
- 在定义字符数组时应保证字符数组长度应始终大于字符串长度
数组作为函数参数
- 退化为指针,即传递的是数组的首地址
rand()函数和srand()函数
- 头文件均为:stdlib.h
- 定义
- int rand(void);
- void srand(unsigned int seed);
- 功能:
- 生成随机数
- rand:在调用此函数产生随机数前,必须先利用srand()设好随机数种子,如果未设随机数种子,rand()在调用时会自动设随机数种子为1,这样的话生成的随机数是伪随机数,每次执行时相同
- srand:用来设置rand的随机数种子,种子相同则生成的随机数相同,通常以时间作为随机数种子
动态内存分配
数组地址是连续的吗
- 数组按栈的方式分配内存,地址是连续的
- 常见变量类型内存分配方式:
- int a; 栈
- char s[] = “abc”; 字符串常量在常量区,数组s在栈上
- char *p1; 栈
- char *p2 = “123456”; 123456\0 在常量区,指针p2在栈上
- static int b = 0; 全局静态初始化区
- p1 = (char *)malloc(10);
- p2 = (char *)malloc(20); 所分配的10/20个字节在堆区,堆区分配方式类似于链表,可能是不连续的
内存泄漏和内存溢出
- 内存泄漏通常指分配的内存未及时释放收回,系统也不能将它分配给需要的程序
- 内存溢出是指内存不能满足正常使用,堆栈已经达到系统设置的最大值,进而导致崩溃
- 内存泄漏会知道堆栈内存不断增大,从而引发内存溢出
不同变量类型之间强制转换
- 长字节转换为短字节:会产生截断。
- 如int转换为char,只取int数据最低的一字节,且是signed的
- 如果是int转换为unsigned char则是unsigned的
- 短字节转换为长字节:需要补位。
- 如char转换为int,char的首位为1,补上0xffffff
- 从unsigned char转换为int,char的首位为0,补上0x000000
- 长字节转换为短字节:会产生截断。
2017.06.02