一、指针
1、二级指针
#include <stdio.h>
int main() {
int val = 0;
int *p_val = &val; //一级指针
int **pp_val = &p_val; //二级指针
**pp_val/*val变量的存储区*/ = 10;
printf("val是%d\n", val);
*pp_val/*p_val指针的存储区*/ = NULL;
printf("p_val是%p\n", p_val);
return 0;
}
#include <stdio.h>
int main() {
char ch = 'e';
char *p_ch = &ch;
int val = 45;
int *p_val = &val;
float fval = 9.4f;
float *p_fval = &fval;
void *p_v = NULL;
p_v = &ch; //无类型指针实际起到字符类型指针的作用
printf("%c\n", *(char *)p_v); //使用无类型指针前先强制类型转换成字符类型指针
p_v = &p_ch; //无类型指针实际起到字符类型二级指针的作用
printf("%c\n", **(char **)p_v/*ch变量存储区*/);
p_v = &p_val; //无类型指针实际起到整数类型二级指针的作用
printf("%d\n", **(int **)p_v/*val变量存储区*/);
p_v = &p_fval; //无类型指针实际起到浮点类型二级指针的作用
printf("%g\n", **(float **)p_v/*fval变量存储区*/);
return 0;
}
2、数据交换
#include <stdio.h>
void swap(int **pp_val/*指向p_val指针*/, int **pp_val1/*指向p_val1指针*/) {
int *p_tmp = NULL;
p_tmp = *pp_val/*p_val*/;
*pp_val/*p_val*/ = *pp_val1/*p_val1*/;
*pp_val1/*p_val1*/ = p_tmp;
}
int main() {
int val = 3, val1 = 7;
int *p_val = &val, *p_val1 = &val1;
swap(&p_val, &p_val1); //语句结束后p_val指针应该指向val1,p_val1指针应该指向val
printf("val是%d,val1是%d\n", val, val1);
printf("*p_val是%d,*p_val1是%d\n", *p_val, *p_val1);
return 0;
}
3、函数指针
#include <stdio.h>
typedef int (*pfunc_t)(int, int); //给函数指针类型起名字,名字就是pfunc_t
int add(int val, int val1) {
return val + val1;
}
int sub(int val, int val1) {
return val - val1;
}
int main() {
/*int (*p_add)(int, int) = NULL; //函数指针声明语句
int (*p_sub)(int, int) = NULL;*/
pfunc_t p_add = NULL, p_sub = NULL; //声明函数指针变量
printf("add是%p\n", add); //函数名称可以代表函数的地址
p_add = add; //p_add指针指向add函数
p_sub = sub;
printf("p_add(3, 8)是%d\n", p_add(3, 8));
printf("p_sub(8, 6)是%d\n", p_sub(8, 6));
return 0;
}
4、回调函数
#include <stdio.h>
typedef void (*pfunc_t)(int *); //创建函数指针类型并命名为pfunc_t
void print_cb(int *p_val) {
printf("%d ", *p_val);
}
void neg_cb(int *p_val) {
*p_val = 0 - *p_val;
}
void for_each(int *p_val, int size, pfunc_t p_func/*声明函数指针形式参数*/) {
int num = 0;
for (num = 0;num <= size - 1;num++) {
p_func(p_val + num/*数组里下标为num存储区的地址*/);
}
}
int main() {
int arr[] = {1, 2, 3, 4, 5};
for_each(arr, 5, print_cb); //把数组里所有存储区的内容显示在屏幕上
printf("\n");
for_each(arr, 5, neg_cb); //把数组里每个存储区的内容都变成相反数
for_each(arr, 5, print_cb);
printf("\n");
return 0;
}
二、动态分配内存
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
int num = 0;
int *p_val = NULL;
srand(time(0));
p_val = (int *)malloc(5 * sizeof(int)); //动态分配5个整数类型存储区并把第一个存储区的地址记录到p_val指针里
if (p_val) {
//把动态分配内存当做数组使用
for (num = 0;num <= 4;num++) {
*(p_val + num) = rand() % 36 + 1; //得到一个1到36之间的随机数并记录到动态分配内存里
}
for (num = 0;num <= 4;num++) {
printf("%d ", *(p_val + num));
}
printf("\n");
free(p_val);//释放内存
p_val = NULL;
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int row;
int col;
} pt;
//从键盘得到一个点的位置并把记录点位置的存储区
//地址作为返回值传递给调用函数
pt *read(void) {
pt *p_pt = (pt *)malloc(sizeof(pt)); //动态分配一个记录点位置的结构体存储区
if (p_pt) {
printf("请输入一个点的位置:");
scanf("%d%d", &(p_pt->row), &(p_pt->col)); //从键盘得到代表点位置的两个整数并记录到动态分配结构体存储区的两个整数类型子存储区里
}
return p_pt; //如果动态分配内存成功就返回首地址,否则返回NULL
}
int main() {
pt *p_pt = read();
if (p_pt) {
printf("点的位置是(%d, %d)\n", p_pt->row, p_pt->col); //从被调用函数动态分配的内存里获得点的位置并显示
free(p_pt);
p_pt = NULL;
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int row;
int col;
} pt;
typedef struct {
pt pt1;
pt pt2;
} rect;
rect *read(void) {
rect *p_rect = (rect *)malloc(sizeof(rect));
if (p_rect) {
printf("请输入水平长方形的位置:");
scanf("%d%d%d%d", &(p_rect->pt1.row), &(p_rect->pt1.col), &(p_rect->pt2.row), &(p_rect->pt2.col));
}
return p_rect;
}
pt *midpt(const rect *p_rect) {
pt *p_mid = (pt *)malloc(sizeof(pt)); //动态分配结构体存储区用来存放中心点位置
if (p_mid) {
p_mid->row = (p_rect->pt1.row + p_rect->pt2.row) / 2;
p_mid->col = (p_rect->pt1.col + p_rect->pt2.col) / 2;
}
return p_mid;
}
int main() {
pt *p_mid = NULL;
rect *p_rect = read();
if (p_rect) {
//返回值不是空指针
p_mid = midpt(p_rect);
if (p_mid) {
//分配成功用来记录中心点
//位置的结构体存储区
printf("中心点位置是(%d, %d)\n", p_mid->row, p_mid->col);
free(p_mid);
p_mid = NULL;
}
free(p_rect);
p_rect = NULL;
}
return 0;
}