菜单导航
一、指针变量
/* 1、定义 普通变量: 数据类型 变量名称 指针变量: 数据类型 * 变量名称; 2、指针变量是什么类型,那么将来就只能保存什么类型变量的地址, 例如 指针变量是int类型, 那么将来就只能保存int类型变量的地址 3、* : 标示这是一个指针变量,代表访问指针变量指向的那一块存储空间 4、指针变量只能存储地址 */ int num = 10; char c = 'a'; float f = 12.f; double d = 22.5; printf("num地址:%p, c地址:%p, f地址:%p, d地址:%p ", &num, &c, &f, &d); printf("num字节: %zu, c字节:%zu, f字节:%zu, d字节:%zu ", sizeof(num), sizeof(c), sizeof(f), sizeof(d)); int *pNum = # char *pC = &c; float *pF = &f; double *pD = &d; printf("pNum地址:%p, pC地址:%p, pF地址:%p, pD地址:%p ", &pNum, &pC, &pF, &pD); printf("pNum字节: %zu, pC字节:%zu, pF字节:%zu, pD字节:%zu ", sizeof(pNum), sizeof(pC), sizeof(pF), sizeof(pD)); printf("改之前的值-->num: %d, c: %c, f: %f, d: %lf ", num, c, f, d); *pNum = 111; *pC = 'c'; *pF = 222.5f; *pD = 333; printf("改之后的值-->num: %d, c: %c, f: %f, d: %lf ", num, c, f, d); /** 打印日志 //2, 1, 0, f, e, d, c, b, a, 9, 8, 7 num地址:0x7fff5fbff758, c地址:0x7fff5fbff757, f地址:0x7fff5fbff750, d地址:0x7fff5fbff748 num字节: 4, c字节:1, f字节:4, d字节:8 pNum地址:0x7fff5fbff740, pC地址:0x7fff5fbff738, pF地址:0x7fff5fbff730, pD地址:0x7fff5fbff728 pNum字节: 8, pC字节:8, pF字节:8, pD字节:8 改之前的值-->num: 10, c: a, f: 12.000000, d: 22.500000 改之后的值-->num: 111, c: c, f: 222.500000, d: 333.000000 */
指针变量的应用练习1:交换两个变量的值
#include <stdio.h> /** 交换变量值:地址传递 */ void swop2(int *v1,int *v2) { int temp = *v1; *v1 = *v2; *v2 = temp; } /** 交换变量值:值传递 */ void swop(int v1,int v2) { int temp = v1; v1 = v2; v2 = temp; } int main() { int a = 20, b = 30; //定义两个int类型变量 printf("交换前a: %i, b: %i ", a, b); //要求交换变量a和b的值 //第一种尝试:传入变量a和b的变量名,在函数内部交换两个变量的值 swop(a, b); printf("。。。传入变量名调用函数交换变量值: "); printf("交换后a: %d, b: %d ", a, b); //第二种尝试: 传入变量a和b的地址,在函数内部交换两个变量的值 swop2(&a, &b); printf("。。。传入变量地址调用函数交换变量值: "); printf("交换后a: %d, b: %d ", a, b); /** 打印结果: 交换前a: 20, b: 30 。。。传入变量名调用函数交换变量值: 交换后a: 20, b: 30 。。。传入变量地址调用函数交换变量值: 交换后a: 30, b: 20 */ printf(" "); return 0; }
指针变量的应用练习2:一个函数传入3个变量,求返回三个变量的和和平均值
#include <stdio.h> /** 传入3个int变量,求3个变量之和 与 平均值 */ int getSum(int v1, int v2, int v3, int *ave){ int sum = v1 + v2 + v3; *ave = sum/3; return sum; } int main() { int v1 = 18, v2 = 998, v3 = 188; int ave; //存储平均值 int sum = getSum(v1, v2, v3, &ave); printf("v1: %d, v2: %d, v3: %d, 和sum: %d, 平均值ave: %d ", v1, v2, v3, sum ,ave); //打印结果: v1: 18, v2: 998, v3: 188, 和sum: 1204, 平均值ave: 401 printf(" "); return 0; }
指针变量注意点:
//1、指针只能保存地址 int num = 10; //int *p = num; //printf("p: %i ", *p); //这样运行会挂 //2、同一个变量可以有多个指针指向它 int *p = # int *p2 = # printf("num: %d, *p: %i, *p2: %d ", num, *p, *p2); *p2 = 88; printf("改后num: %d, *p: %i, *p2: %d ", num, *p, *p2); /** 打印日志: num: 10, *p: 10, *p2: 10 改后num: 88, *p: 88, *p2: 88 */ //3、指针的指向可以修改 int num2 = 18; p2 = &num2; *p2 = 99; printf("num: %d, *p: %d, *p2: %d, num2: %d ", num, *p, *p2, num2); //打印日志:num: 88, *p: 88, *p2: 99, num2: 99 //4、不要访问野指针:野指针值没有赋值的指针 int *p3 = NULL; //*p3 = 12; //这样运行会挂
// 5、指针变量和变量类型要一致,即int类型指针只能存储int类型的变量的地址
// 因为当我们利用指针去取值的时候,系统会自动根据指针的类型来确定应该取对少个字节的值. int intValue = 518; char *p = &intValue; printf("*p: %i ", *p); /** 打印日志:*p: 6 为什么? intValue = 518 的二进制为: 0000 0000 0000 0000 0000 0010 0000 0110 指针变量p是char类型,只会存储char类型的地址,即一个字节的地址, 所以指针变量p只存储了intValue的最小字节地址,即0000 0110这个字节的地址,转成十进制为:6 */
多级指针测试:
//一级指针 char ch = 'a'; char *p = &ch; *p = 'b'; printf("c: %c, *p: %c ", ch, *p); //打印日志:c: b, *p: b //二级指针 char **p2 = &p; //指向指针的指针,也占用8个字节 **p2 = 'd'; printf("ch: %c, *p: %c, **p2: %c ", ch, *p, **p2); //打印日志:ch: d, *p: d, **p2: d //三级指针 char ***p3 = &p2; ***p3 = 'f'; printf("ch: %c, *p: %c, **p2: %c, ***p3: %c ", ch, *p, **p2, ***p3); //打印日志:ch: f, *p: f, **p2: f, ***p3: f printf("地址--》ch: %p, p: %p, p2: %p, p3: %p ", p, p2, p3, &p3); //打印日志:地址--》ch: 0x7fff5fbff76b, p: 0x7fff5fbff760, p2: 0x7fff5fbff758, p3: 0x7fff5fbff750
二、指针和数组
//指针和数组 int arr[] = {88, 18, 58}; int *pi = arr; //arr是数组名,也是数组地址,也是数组中第一个元素的地址 printf("arr: %p, pi: %p, arr[0]: %p ", arr, pi, &arr[0]); //打印日志:arr: 0x7fff5fbff760, pi: 0x7fff5fbff760, arr[0]: 0x7fff5fbff760 //pi + 1 : 表示地址+1,本质是地址+该数据类型的字节个数; pi相当于数组名 printf("pi+1: %p, arr+1: %p ", pi+1, arr+1); printf("*(pi+1): %i, *(arr+1): %i, pi[1]: %i, arr[1]: %i ", *(pi+1), *(arr+1), pi[1], arr[1]); /** 打印日志: pi+1: 0x7fff5fbff764, arr+1: 0x7fff5fbff764 *(pi+1): 18, *(arr+1): 18, pi[1]: 18, arr[1]: 18 */ //字符指针和字符数组 char cArr[] = {'a', 'B', 'c', 'D', '