近段复习C语言,感觉C语言相对于C++、Java等高级语言最大的特点就是:简洁紧凑、灵活方便。C语言特征不多,带有面向硬件思维,小巧而精炼。
C语言非常贴近底层,要真正理解指针的本质,还需要些微机原理、计算机组成与原理、操作系统和编译原理等背景知识。变量声明后,相当于和一块存储区的绑定,即把这块存储区暂时(变量生命周期内)叫做这个名字(变量),编译后就变成了对应内存的地址。这块存储区有其编址(编译器和操作系统)决定,对变量赋值,即往这块存储区写数据。
指针是这样一种变量,存放的是指定数据类型的首字节地址(例如32位程序可理解为4B无符号int)。通过指针可以对其指向的变量(指针存放了其指向变量的地址)进行操作。既然指针也是一种变量,那么其也有所占用的存储区,这快存储区地址也可以存放在指向其的指针中,这就是指向指针的指针。
一个典型的C程序中:
C语言中结构体和指针就可以描述很多经典数据结构,下面通过一个链表的例子来总结:
#include <stdio.h> #include <stdlib.h> typedef int ElemType; typedef struct Node { ElemType data; struct Node *next; } Node; //c语言中的定义,c语言的一些语法细节和c++区别还较大 //data属性是用来存放数据的,其他的都是载体而已,从设计的角度出发 typedef Node *LinkList; //定义LinkList,自定义链表的指针变量,指向链表的地址 //typedef struct Node *LinkList; //这句也正确,上面的typedef定义了Node /* typedef 对已经存在的类型加一个别名 e.g. {typedef int NUM[100]; NUM n;} <=> int n[100]; */ // 初始化一个Node,开辟地址 int initList(LinkList *L) { //这里的传递的参数是指向指针(结构体指针)的指针 //c语言不可以传递引用,c++才可以,严蔚敏数据结构传递的是c++的引用,使用&符号 //在主函数中,实参可以是:要传递的地址,一个本类型的指针变量,本质都是拷贝地址到调用函数的指针变量中 *L = (LinkList) malloc(sizeof(Node)); //*L就是指针L指向的数据 if (!(*L)) return 0; //内存不足是就会FALSE (*L)->data = 0; (*L)->next = NULL; // 这里的 *L 后就是取得 指向结构体 的指针 return 1; } //结构体指针:结构体变量.成员名;(*p).成员名;p->成员名 [p为结构体指针变量] int creatList(LinkList *L, int n) { LinkList p; int i; *L = (LinkList) malloc(sizeof(Node)); //数据存放在变量中,变量存放在地址中 (*L)->next = NULL; for (i = 0; i < n; i++) { p = (LinkList) malloc(sizeof(Node)); //创建一个节点 p->data = rand() % 100 + 1; //来自库 stdlib.h p->next = (*L)->next; (*L)->next = p; } printf("Creat LinkList succeed."); return 1; } int visitList(LinkList L) { printf("\nVisit LinkList: "); L = L->next; while (L != NULL) { printf("%d ", L->data); L = L->next; } return 1; } int insertList(LinkList L, ElemType e, int n) { int i; //由于L是头,不算是第一个节点,不存放元素 LinkList node; node = (LinkList) malloc(sizeof(Node)); //面向对象中的new,开辟在堆中 node->data = e; for (i = 0; i < n - 1 && L != NULL; i++) { //查到 n-1号节点的后面 L = L->next; //L初始是头结点,不存放数据,查到n循环n-1次 } if (n < 1) { printf("\nInsert index must >0"); return 0; }<span style="font-family: Arial, Helvetica, sans-serif;">//判断边界条件</span> if (L == NULL) { printf("\nInsert index is out of length"); return 0; } node->next = L->next; L->next = node; printf("\nInsert into index: %d, value is:%d", n, node->data); return 1; } int main() { LinkList L; //L是一个指针变量,指向结构体 printf("&L is %d, L is %d\n", &L, L); printf("size of int is %d\n", sizeof(int)); printf("size of char is %d\n", sizeof(char)); printf("size of int* is %d\n", sizeof(int*)); printf("size of LinkList is %d\n", sizeof(LinkList)); printf("size of LinkList* is %d\n", sizeof(LinkList*)); ElemType e; e = 99; creatList(&L, 10); //创造一个链表 printf("\n&L is %d,L is %d, &(L->data) is %d", &L, L, &(L->data)); printf("\n&L is %d,L is %d, &(L->next) is %d", &L, L, &(L->next)); visitList(L); //遍历每个元素 insertList(L, e, 3); // 这里的ElemType传递了复制(也可以传递地址通过指针) visitList(L); //遍历每个元素 return 0; }输出的结果:
&L is 2686696, L is 0 size of int is 4 size of char is 1 size of int* is 4 size of LinkList is 4 size of LinkList* is 4 Creat LinkList succeed. &L is 2686696,L is 7614288, &(L->data) is 7614288 &L is 2686696,L is 7614288, &(L->next) is 7614292 Visit LinkList: 65 63 59 79 25 70 1 35 68 42 Insert into index: 3, value is:99 Visit LinkList: 65 63 99 59 79 25 70 1 35 68 42