一、指针
1、指针是地址,任何类型的指针都可以指向内存的任何位置。
一个表示内存地址的长整数而已。
一个数据在内存中的地址,无论什么数据类型。
2、使用指针的好处:
能够为调用函数灵活地修改实参变量的值。
支持动态内存分配,能够方便的实现动态的数据结构。
可以提高某些程序的效率。
实现缓冲方式的文件存取。
3、指针表达式:原则上讲,涉及指针的表达式符合其它C表达式的规则。
(1)printf("%p",...)//以宿主计算机使用的格式显示地址
(2)指针转换:
void *型:常用来说明基类型未知的指针。
-->它允许函数指定参数,此参数可以接受任何类型的指针变量而不必报告类型失配。
-->其它类型的指针转换时必须使用明确的强制类型转换。
-->0不需要强制转换,因为它是NULl指针。
4、指针算术:可以作用于指针的操作只有加法和减法
-->指针与整数的加、减法。
-->从一个指针中减去另一个指针(求指针偏移量)
5、指针比较:主要用于两个或多个指针指向共同对象的情况。
6、指针的初始化:
(1)非静态局部指针已声明但未赋值前,其值不确定。
(2)全局和静态局部指针自动初始化为 NULL。
(3)赋值前使用指针,不仅可能导致程序瘫痪,还有可能使 OS(Operating System)崩溃,错误可谓严重之至!
(4)[习惯用法]对于当前没有指向合法的内存空间的指针,为其赋值 NULL。
因为 C 保证空地址不存在对象,所以任何空指针都意味着它不指向任何对象,不应该使用它。
用空指针来说明不用的指针基本上就是程序员遵守的协定。
思考:
{ int *p = NULL; *p = 1; }可行吗?
7、函数指针与指针函数
函数指针是一个指向函数的指针,而指针函数值只是说明他是一个返回值为指针的函数。
函数指针用来指向一个函数。
(1)函数指针
--->函数指针的定义:函数返回值类型 (*指针变量名)(形参列表)
定义函数指针时注意:
函数指针和它指向的函数的参数个数和类型都应该是一致的;
返回值类型也必须是一致的。
--->函数指针的赋值
int func(int x);//声明一个函数
int (*p)(int x);//声明一个函数指针
p = func; 或 p = &func; //将func函数的首地址赋给指针
(2)指针函数
一个函数不仅可以带回一个整型数据的值或者字符型值,还可以带回指针类型的数据,使其指向某个地址单元。
--->函数指针的定义:函数返回值类型 *函数名(形参列表)
总结:
函数指针是一个指向函数的指针,而指针函数只是说明它是一个返回值为指针的函数;
函数指针可以用来指向一个函数。
8、动态分配内存空间:指程序在运行中取得内存空间。
全局标量在编译时分配内存空间,非静态局部变量使用栈区,两者在运行时使用固定长度的内存空间。
(1)为了实现动态的数据结构,C动态函数在堆区分配内存空间,堆是系统的自由内存区。
(2)核心函数:malloc()和free()
(3)堆区是有限的,分配内存空间后必须检查malloc()的返回值,确保指针使用前它是非空的。
(4)绝对不要用无效的指针调用free(),否则将破坏自由表。
二、堆和栈
三、指针与数组
数组和指针关系非常紧密。
一维数组名可被不严格地认为是指针常量:可执行指针的操作;可按地址单元赋值和引用;也可以用来初始化同型的指针变量,但不能对一维数组名赋值。
a[1] = *(a + 1)
1、纯指针数组(int *p; int **p):这样的数组是可变长的,因此不能用sizeof()求数组大小,但可以实现多维动态,而且存取效率较高。
四、指针数组与数组指针
指针数组:array of pointers,即用于存储指针的数组,也就是数组元素都是指针
数据类型 *数组名[元素数];
表示:数组中的元素都是被定义类型的指针。
数组指针:a pointers to an array,即指向数组的指针
数据类型 (* 数组名)[元素数]
表示:指向数组的指针
四、编译预处理
1、ANSI C定义的标准预处理指令
#define
#include
#if
#ifdef
#ifndef
#else
#elif
#endif
预处理器处理的对象是预处理指令,输出是“翻译单元(存放在内存中的临时文件)”
编译器接受预处理器的输出,并把源代码换成包含机器语言指令的目标文件。
2、书写规定与习惯
---每条指令必须单独占用一行
---每行末不加“;”
---一般使用全部大写来表示标识符
---预处理指令可以出现的程序的任何位置,通过合理的使用这些指令, 可以提高程序的可读性和移植性。
3、#define
4、#include
5、条件编译
阅读(543) | 评论(0) | 转发(0) |