指针和数组
- 指针经常和goto语句一起使用创造出一些难以理解的代码
- 取地址运算&只能作用于在内存中的变量或者数组元素,对于表达式、常量或者寄存器变量不适用
- 指针的定义int *ip;意思是 *ip是int型
- 每个指针变量都指向一个具体的数据类型,但是指向空的指针除外,void *用来存储其他类型的指针,但是void类型的指针不能用间接引用取其值
- 任何能用数组下表完成的操作都可以用指针完成,而且指针完成的速度更快一些
- 指针+1指向下一个元素,对应于char类型就是下一个字节,对应于int就是后四个字节
- 数组名就是第一个元素的地址,就是指针
- 在计算a[i]的时候,C会把它转化为 *(a + i),这两种表达方式相同
- 数组名和指针的一个不同就是:指针是变量,可以进行+或-操作,数组名不是变量
- 传送的实参是数组名的时候,真正传送的是第一个元素的地址
- 对于指针的操作,越界比较或者指针的算术运算不会出问题,但是如果要越界赋值就会报错,因为你对越界所访问的内存没有修改权限,你可以读出它的值但是你不能修改它
- C语言中,0永远不是一个有效的地址,所以返回0可以指示出错
- 指针和整型之间不能替换,但是0是仅有的例外。0可以赋值给指针,指针也可以和0比较,符号常量NULL常用来代替0,因为这样表意更明显
- 如果p和q指向同一个数组的元素,那指针之间可以比较(==、!=、<、>等)
在指针的算术运算中,指向不同数组元素之间的运算没有定义,但是一个例外是可以使用数组最后一个元素的下一个元素的地址
指针的四种合法运算:①同类型指针的赋值②指针加减整数③指向同一数组的指针的比较和相减④与整数0的比较或者赋值0给指针
- 字符串常量“I am a string”是字符数组
- 像上述字符串传入到printf函数中的时候,printf函数得到的是指向字符串数组第一个元素的指针
- 定义一个字符指针并把一个字符串赋值为它,是让指针指向存储这个字符串的数组,但是字符串常量存储在常量存储区,所以不能通过指针修改这个字符串常量
- t++中++和 的优先级一样高,并且是右结合,所以这个表达式的意思是取出当前指针所以的内容,并让指针指向下一个元素
- 指针是一个变量,那么指针当然可以保存在数组中,保存指针的数组被称为指针数组,指针数组名仍然是第一个元素的地址
- 数组只有在定义的时候才能进行整体赋值
- 如果传递的参数是一个二维数组,那么这个数组的列必须指明,行数可以不指明
二维指针和指针数组:二维数组真真正正的拥有那么多可以操作的存储空间,而指针数组,在指针未被赋值之前只有存储指针的空间。指针数组的好处是列可以不同长
main函数被调用时,有两个参数 argc(argument count)和argv(argument vector)。argv是一个指向字符串数组的指针。argv[0]是程序的名字,所以argc至少是1
结构体
- 结构体可以被复制,赋值,传给函数,被函数返回。对于结构体合法的操作仅有:作为整体赋值和复制、用&取它的地址以及访问其成员
- 传指向结构体的指针比传结构体方便多了
- sizeof不能在#if中用,因为预处理器不分析类型名,但是#define中的表达式不是由预处理器求值,所以在这里合法
- 结构体中包含指向自身的指针是合法的,但是包含自身就是非法的了
- 在typedef声明的类型出现的位置是在变量名的位置出现,而不是在紧跟在typedef之后,例如typedef int ( PEI) (char , char *);意思是定义PEI为一直指向参数为两个指针的函数的指针,就是PEI是一个指向函数的指针,它出现的位置是正常情况下我们定义变量名的位置而不是紧跟在typedef之后
- 使用typedef的目的:①定义那些机器相关的类型②便于程序文稿或者理解
- 共用体只能对其中第一个元素初始化,就是定义共用体是排在第一的元素
输入和输出
- 符号常量EOF定义为-1,使用EOF便于移植
- 在许多环境中,可以通过<输入重定向符将程序输入从键盘更改为某个文件,同理对于>输出重定向
- 像getchar和putchar以及tolower这样的“函数”常常是宏,这样就避免了函数调用的开销
- 在printf中出现在%号后面的东西可以包括:①符号-,代表左对齐②表示至少输出多少位的数,如果需要的话会在左边填充空格(或者在左对齐的情况下在右边填充空格)③小数点④小数点后的数,精度,表示从一个字符串中打印最多多少个字符;或者小数点后多少位小数
- printf用第一个参数确定后面有多少个参数以及他们的类型,不匹配会出错
- sprintf同printf一样,只是把结果保存到第一个指针参数中
- scanf返回的是成功匹配赋值变量的个数
- 当需要读取格式不确定的输入时,最好先一次读一行,然后用sscanf处理
- 文件读取时,在读和写之前应该先用库中的函数open打开才行
- 文件的打开模式有三种,“r”读,“w”写,“a”追加;一些系统区分文本和二进制,对于区分二进制的,“b”必须加到打开模式串后面
- 如果要写或者追加的文件不存在,就创建一个;如果以写的方式打开一个文件,那么这个文件中的内容都消失;尝试读一个不存在的文件是错误的;如果有错误,文件指针返回NULL
- C程序开始执行时,操作系统有责任打开三个文件提供文件指针:标准输入,标准输出以及标准错误处理;相应的指针是stdin、stdout以及stderr
- stdin和stdout是常量而不是变量
- 行输入和输出:char *fgets(char *line, int maxline, FILE *fp)取下一行输入到字符数组line中,最多maxline-1个字符;通常fgets返回line,文件结束或者错误返回NULL
- int fputs(char *line, FILE *fp)写一行,但是不包含换行符
- 类似的,gets和puts有相同的效果,但是它们仅作用于标准输入输出,并且gets不包含结尾的\n,但是puts却把它加上去了
- void *malloc(size_t n) void *calloc(size_t n, size_t size)必须强制类型转换返回值