面试:
unsigned int *p1 = #
int *p2 = #
1 #define _CRT_SECURE_NO_WARNINGS 2 3 #include<stdio.h> 4 #include<stdlib.h> 5 6 main() 7 { 8 int num = -1; 9 unsigned int *p1 = # 10 int *p2 = # 11 12 printf("%u,%d", *p1, *p2); 13 14 system("pause"); 15 }
输出结果:
4294967295,-1请按任意键继续. . .
//左边是指针指向内容的大小,右边是指针的大小
1 #define _CRT_SECURE_NO_WARNINGS 2 3 #include<stdio.h> 4 #include<stdlib.h> 5 6 main() 7 { 8 int *p; 9 double *pb; 10 //左边是指针指向内容的大小,右边是指针的大小 11 printf("%d,%d ", sizeof(*p), sizeof(p)); 12 printf("%d,%d ", sizeof(*pb), sizeof(pb)); 13 14 system("pause"); 15 }
//指针相减,如果值为正,p1在p2后面,值为负,p1在p2后面
//具体之差就意味着指针之间相隔几个元素的大小
//具体之差不是地址之差,而是地址之差除以指向元素的大小
1 #define _CRT_SECURE_NO_WARNINGS 2 3 #include<stdio.h> 4 #include<stdlib.h> 5 6 main() 7 { 8 int a = 10; 9 int b = 20; 10 int *p1 = &a; 11 int *p2 = &b; 12 13 int num = p1 - p2; 14 //指针相减,如果值为正,p1在p2后面,值为负,p1在p2后面 15 //具体之差就意味着指针之间相隔几个元素的大小 16 //具体之差不是地址之差,而是地址之差除以指向元素的大小 17 printf("%x,%x,%d", p1, p2, num); 18 19 system("pause"); 20 }
1、 若有p=a(p指向数组a),则:
np++(或p+=1),表示p指向下一元素。
n*p++与*(p++)等价。同样优先级,结合方向为自右向左。
n*(p++) 与*(++p)。
前者是先取*p的值,后使p值加1,相当于a[i++];后者是先使p加1,再取*p,相当于a[++i]。
n(*p)++表示p所指向的元素值加1,而非指针值加1。
2、 a是一个数组
int *p=a;
p++;
p++是先引用,再自增,自增一个sizeof(指针指向的类型)的大小。
++指针在数组内部向前移动一个元素的大小
p=p+1;
指针在数组内部向前移动一个元素的大小
*p++ 等价于 *(p++) , ++是先引用再自增
指针在数组内部向前移动一个元素的大小
++p 先自增,再引用
*(p++) 和 *(++p)的区别?
*(p++) 先引用*p,再自增p++,a[i++]
*(++p) 先自增,再引用
(*p)++ 取出指针指向的内容自增一下
1 #define _CRT_SECURE_NO_WARNINGS 2 3 #include<stdio.h> 4 #include<stdlib.h> 5 6 main1()//p++ 7 { 8 int a[10] = { 1,2,3,4,5 ,6,7,8,9,10 }; 9 int i; 10 int *p = a; 11 12 for (i = 0;i < 10;i++) 13 { 14 printf("%d,%x ", a[i], &a[i]); 15 } 16 17 printf("%x ", p); 18 19 printf("%x ", p++);//++就是先引用,再自增,自增一个sizeof指针指向的类型的大小 20 21 printf("%x ", p);//++指针在数组内部向前移动一个元素的大小 22 23 system("pause"); 24 } 25 26 main2()//++p 27 { 28 int a[10] = { 1,2,3,4,5 ,6,7,8,9,10 }; 29 int i; 30 int *p = a; 31 32 for (i = 0;i < 10;i++) 33 { 34 printf("%d,%x ", a[i], &a[i]); 35 } 36 37 printf("%x ", p); 38 39 printf("%x ", ++p);//++就是先自增,再引用 40 41 printf("%x ", p);//++指针在数组内部向前移动一个元素的大小 42 43 system("pause"); 44 } 45 46 main3()//p = p + 1 47 { 48 int a[10] = { 1,2,3,4,5 ,6,7,8,9,10 }; 49 int i; 50 int *p = a; 51 52 for (i = 0;i < 10;i++) 53 { 54 printf("%d,%x ", a[i], &a[i]); 55 } 56 57 printf("%x ", p); 58 p = p + 1;//指针在数组内部向前移动一个元素的大小 59 printf("%x ", p); 60 61 system("pause"); 62 } 63 64 main4()//*p++ 65 { 66 int a[10] = { 1,2,3,4,5 ,6,7,8,9,10 }; 67 int i; 68 int *p = a; 69 70 for (i = 0;i < 10;i++) 71 { 72 printf("%d,%x ", a[i], &a[i]); 73 } 74 75 printf("%x ", p); 76 printf("%d ", *p++);//++先引用*p,再自增p++,*p=1,等价于*(p++),类似a[i++] 77 printf("%x ", p);//指针在数组内部向前移动一个元素的大小 78 printf("%d ", a[0]); 79 80 system("pause"); 81 } 82 83 main5()//*(++p) 84 { 85 int a[10] = { 1,2,3,4,5 ,6,7,8,9,10 }; 86 int i; 87 int *p = a; 88 89 for (i = 0;i < 10;i++) 90 { 91 printf("%d,%x ", a[i], &a[i]); 92 } 93 94 printf("%x ", p); 95 printf("%d ", *(++p));//++先自增,再引用 96 printf("%x ", p); 97 printf("%d ", a[0]); 98 99 system("pause"); 100 } 101 102 main6()//(*p)++ 103 { 104 int a[10] = { 1,2,3,4,5 ,6,7,8,9,10 }; 105 int i; 106 int *p = a; 107 108 for (i = 0;i < 10;i++) 109 { 110 printf("%d,%x ", a[i], &a[i]); 111 } 112 113 printf("%x ", p); 114 printf("%d ", (*p)++);//取出指针指向的内容自增一下 115 printf("%x ", p); 116 printf("%d ", a[0]); 117 118 system("pause"); 119 } 120 121 main()//++(*p) 122 { 123 int a[10] = { 1,2,3,4,5 ,6,7,8,9,10 }; 124 int i; 125 int *p = a; 126 127 for (i = 0;i < 10;i++) 128 { 129 printf("%d,%x ", a[i], &a[i]); 130 } 131 132 printf("%x ", p); 133 printf("%d ", ++(*p));//先自增,再引用 134 printf("%x ", p); 135 printf("%d ", a[0]); 136 137 system("pause"); 138 }
//地址的比较没有意义,只能判断哪个地址也就是内存编号比较靠前
//不在数组,没有太大意义
1 #define _CRT_SECURE_NO_WARNINGS 2 3 #include<stdio.h> 4 #include<stdlib.h> 5 6 main() 7 { 8 int num1 = 18, num2 = 28; 9 int *p1 = &num1; 10 int *p2 = &num2; 11 12 printf("num1=%d,*p1=%d ", num1, *p1); 13 printf("num2=%d,*p2=%d ", num2, *p2); 14 15 printf("%x,%x ", &num1, p1); 16 printf("%x,%x ", &num2, p2); 17 18 //地址的比较没有意义,只能判断哪个地址也就是内存编号比较靠前 19 //不在数组,没有太大意义 20 if (p1 > p2) 21 { 22 printf("p1的地址比较靠后"); 23 } 24 else 25 { 26 printf("p2的地址比较靠后"); 27 } 28 29 system("pause"); 30 }
指针比较
if (p1 == p2)为真,则p1和p2指向同一个变量
1 #define _CRT_SECURE_NO_WARNINGS 2 3 #include<stdio.h> 4 #include<stdlib.h> 5 6 main() 7 { 8 int num = 10; 9 int *p1 = # 10 int *p2 = # 11 12 if (p1 == p2) 13 { 14 printf("指向同一个变量 "); 15 } 16 else 17 { 18 printf("不是指向同一个变量"); 19 } 20 21 //num,*p1,*p2三者改变其中一个,另外两个都会改变 22 num = 3;//直接赋值 23 printf("%d,%d,%d ", num, *p1, *p2); 24 25 *p1 = 4;//间接赋值 26 printf("%d,%d,%d ", num, *p1, *p2); 27 28 *p2 = 5;//间接赋值 29 printf("%d,%d,%d ", num, *p1, *p2); 30 31 system("pause"); 32 }
p++;//指针++,就是按照指针类型的大小,前进一个类型的大小,如果是int,前进4个字节
printf("%d", *p);//指针++,只有在数组内部才有意义
1 #define _CRT_SECURE_NO_WARNINGS 2 3 #include<stdio.h> 4 #include<stdlib.h> 5 #include<windows.h> 6 7 main() 8 { 9 int num = 100; 10 int *p = # 11 p++;//指针++,就是按照指针类型的大小,前进一个类型的大小,如果是int,前进4个字节 12 printf("%d", *p);//指针++,只有在数组内部才有意义 13 14 system("pause"); 15 }
int *p1 = #//地址的赋值
int *p2 = p1;//指针的赋值
//num,*p1,*p2一个改变,其他两个都会跟着改变
1 #define _CRT_SECURE_NO_WARNINGS 2 3 #include<stdio.h> 4 #include<stdlib.h> 5 6 main() 7 { 8 int num = 10; 9 int *p1 = #//地址的赋值 10 int *p2 = p1;//指针的赋值 11 //num,*p1,*p2一个改变,其他两个都会跟着改变 12 13 *p2 = 3; 14 15 printf("%d,%d,%d", num, *p1, *p2); 16 17 system("pause"); 18 }
//.c比较宽泛,所以只是警告
//.cpp就是类型不匹配
//整数与指针最好不要直接运算
1 #define _CRT_SECURE_NO_WARNINGS 2 3 #include<stdio.h> 4 #include<stdlib.h> 5 6 main() 7 { 8 int a = 5; 9 10 int *p = a; 11 12 *p = 3; 13 //.c比较宽泛,所以只是警告 14 //.cpp就是类型不匹配 15 //整数与指针最好不要直接运算 16 17 system("pause"); 18 }
//指针存储的是地址,地址是首地址,从哪里开始
//从哪里结束,由类型决定
//类型决定长度,决定如何解析
1 #define _CRT_SECURE_NO_WARNINGS 2 3 #include<stdio.h> 4 #include<stdlib.h> 5 6 main() 7 { 8 char ch = 'A'; 9 int num = 45; 10 double db = 12.5; 11 char *p1 = &ch; 12 int *p2 = # 13 double *p3 = &db; 14 15 printf("%x,%x,%x ", p1, p2, p3); 16 printf("%c,%d,%f ", *p1, *p2, *p3); 17 //指针存储的是地址,地址是首地址,从哪里开始 18 //从哪里结束,由类型决定 19 //类型决定长度,决定如何解析 20 21 system("pause"); 22 }
二级指针:
第一,函数内部改变外部的指针变量用到二级指针
第二,游戏外挂改变外部的指针变量
函数调用,改变原来的数据,传地址,可以根据地址改变;传数据,就无法改变(形式参数会新建一个变量,接收实际参数的值)
1 #define _CRT_SECURE_NO_WARNINGS 2 3 #include<stdio.h> 4 #include<stdlib.h> 5 6 void change(int *p) 7 { 8 *p = 99; 9 } 10 11 main() 12 { 13 int num = 10; 14 15 int *p = # 16 17 //change(10);传递实际参数,不会改变 18 //change(num);传递实际参数,不会改变 19 //change(*p);传递实际参数,不会改变 20 21 change(p); 22 23 printf("%d", num); 24 25 system("pause"); 26 }
int *p = #
1 #define _CRT_SECURE_NO_WARNINGS 2 3 #include<stdio.h> 4 #include<stdlib.h> 5 6 main() 7 { 8 int num = 10; 9 int *p = #//&num是一个地址,是一个常量 10 //p是一个指针变量,可以存储一个地址 11 12 system("pause"); 13 }
int * p;
int * 是数据结构。
p 是变量名字。
* p 是以 p 的内容为地址的变量。
指针:表示一些复杂的数据结构,快速的传递数据,使函数返回一个以上的值,能直接访问硬件,能够方便的处理字符串,是理解面向对象语言中引用的基础。
总结:指针是C语言的灵魂。
地址:内存单元的编号,从零开始的非负整数,范围:4G
指针:
1 #include <stdio.h> 2 main() 3 { 4 int * p; /* int *是数据类型,所谓int *类型就是存放int变量地址的类型,表示p变量存放的是int类型变量的地址 5 p是变量的名字 */ 6 int i = 3; 7 8 int j; 9 10 p = &i; /* OK 11 1 p保存了i的地址,因此p指向i。 12 2 p不是i,i也不是p,更准确的说:修改p的值不影响i的值,修改i的值也不会影响p的值 13 3 如果一个指针变量指向了某个普通变量,则*指针变量 就完全等同于 普通变量 14 例子:如果p是个指针变量,并且p存放了普通变量i的地址,则p指向了普通变量i 15 *p 就完全等同于 i 16 或者说:在所有出现*p 的地方都可以替换成i 17 在所有出现i 的地方都可以替换成*p 18 *p 就是以 p 的内容为地址的变量 19 */ 20 21 //p = i; // ERROR,因为类型不一致,p只能存放int类型变量的地址,不能存放int类型变量的值 22 23 //p = 55; // ERROR,原因同上 24 25 j = *p; //等价于j=i 26 27 printf("i=%d,j=%d,*p=%d ", i, j, *p); 28 }
输出格式:
i=3,j=3,*p=3
请按任意键继续. . .
a b 互换功能
不能完成互换功能
1 #include <stdio.h> 2 void huhuan(int a, int b) /*不能完成互换功能*/ 3 { 4 int t; 5 t = a; 6 a = b; 7 b = t; 8 9 return; 10 } 11 main() 12 { 13 int a = 3; 14 int b = 5; 15 16 huhuan(a, b); 17 18 printf("a=%d,b=%d", a, b); 19 }
可以完成互换功能
p 是 int *,* p 是 int
1 #include <stdio.h> 2 void huhuan1(int * p, int * q) 3 { 4 int t; /* 如果要互换*p和*q的值,则t必须定义成int,不能定义为int*,否则语法出错 */ 5 6 t = *p; /* p是int *,* p int */ 7 *p = *q; 8 *q = t; 9 } 10 main() 11 { 12 int a = 3; 13 int b = 5; 14 15 huhuan1(&a, &b); /* 16 huhuan1(*p, *q);错误 17 huhuan1(a, b);错误 18 */ 19 20 printf("a=%d,b=%d", a, b); 21 }
* 的含义
1 乘法
2 定义指针变量
出现在定义语句,代表定义了一个指针变量。
int * p;
定义了一个名字叫 p 的变量,int * 表示 p 只能存放 int 变量的地址
3 指针运算符,间址运算符
出现在执行语句,代表引用当前指针变量的内容。
该运算符放在已经定义好的指针变量的前面
如果 p 是一个已经定义好的指针变量
则 * p 表示以 p 的内容为地址的变量
* 与 & 是逆预算
* 间址运算符,求当前地址的内容、元素
& 地址运算符,求当前内容、元素的地址
a[0]a[1] a[2]a[3] a[4]
11 22 33 44 55
p q
指针内容相减:
* q - * p = 22;
指针相减:
q - p = 2;
如何通过被调函数修改主调函数普通变量的值
1 实参必须为该普通变量的地址
2 形参必须为指针变量
3 在被调函数中通过
* 形参名 = ...
的方式就可以修改主调函数相关变量的值
1 #include <stdio.h> 2 main() 3 { 4 int * p; /*建议写这个*/ 5 int *p; /*都一样*/ 6 int* p; /*都一样*/ 7 int*p; /*都一样*/ 8 }
8.1 用指针指向两个变量,通过指针运算选出值小的那个数。
1 #include <stdio.h> 2 main() 3 { 4 int a, b, min, *pa, *pb, *pmin; 5 pa = &a; 6 pb = &b; 7 pmin = &min; 8 scanf("%d %d", pa, pb); 9 printf("a=%d,b=%d ", a, b); 10 11 *pmin = *pa; 12 if (*pa > * pb) 13 { 14 *pmin = *pb; 15 } 16 printf("min=%d ", min); 17 }
8.2 编写函数 myadd(int * a, int * b) ,函数中把指针 a 和 b 所指的存储单元中的两个值相加,然后将和值作为函数值返回。在主函数中输入两个数给变量,把变量地址作为实参,传送给对应形参。
1 #include <stdio.h> 2 int myadd(int * a, int * b) 3 { 4 int sum; 5 sum = *a + *b; 6 return sum; 7 } 8 9 main() 10 { 11 int x, y, z; 12 printf("Enter x,y:"); 13 scanf("%d %d", &x, &y); 14 z = myadd(&x, &y); 15 printf("%d+%d=%d ", x, y, z); 16 }
8.3 调用 swap 函数,交换主函数中变量 x 和 y 中的数据。
1 #include <stdio.h> 2 void swap(int *, int *); 3 main() 4 { 5 int x = 30, y = 20; 6 printf("(1)x=%d y=%d ", x, y); 7 swap(&x, &y); 8 printf("(4)x=%d y=%d ", x, y); 9 } 10 11 void swap(int * a, int * b) 12 { 13 int t; 14 printf("(2)a=%d b=%d ", *a, *b); 15 t = *a; 16 *a = *b; 17 *b = t; 18 printf("(3)a=%d y=%d ", *a, *b); 19 }
8.4 编写函数 order(int * a, int * b) ,使调用函数中的第一个实参总是存放两个数中的较小的数,第二个参数存放两个数中较大的数。
1 #include <stdio.h> 2 void swap(int * x1, int * x2) 3 { 4 int t; 5 t = *x1; 6 *x1 = *x2; 7 *x2 = t; 8 } 9 10 void order(int * a, int * b) 11 { 12 if (*a > * b) 13 { 14 swap(a, b); 15 } 16 } 17 18 main() 19 { 20 int x, y; 21 printf("Enter x,y:"); 22 scanf("%d %d", &x, &y); 23 printf("x=%d y=%d ", x, y); 24 order(&x, &y); 25 printf("x=%d y=%d ", x, y); 26 }
8.5 以下函数把主函数中变量 i 和 j 中存放较大数的那个地址作为函数值传回。
1 #include <stdio.h> 2 int * fun(int *, int *); /* 函数说明语句 */ 3 main() 4 { 5 int * p, i, j; 6 printf("Enter two number:"); 7 scanf("%d %d", &i, &j); 8 p = fun(&i, &j); /* p将得到i或j的地址 */ 9 printf("i=%d,j=%d,* p=%d ", i, j, *p); 10 } 11 12 int * fun(int * a, int * b) 13 { 14 if (*a > * b) 15 { 16 return a; 17 } 18 return b; 19 }
8.6 请编写程序,其功能是对传送过来的两个浮点数求出和值与差值,并通过形参传送回调用函数。
1 #include "Stdio.h" 2 void f(float x, float y, float *ps, float *pd) 3 { 4 *ps = x + y; 5 *pd = x - y; 6 } 7 main() 8 { 9 float x, y, sum, diff; 10 printf("input x y=? "); 11 scanf("%f %f", &x, &y); 12 f(x, y, &sum, &diff); 13 printf("%f+%f=%f %f-%f=%f", x, y, sum, x, y, diff); 14 }
8.7 请编写函数,对传送过来的三个数选出最大数和最小数,并通过形参传回调用函数。
1 #include "Stdio.h" 2 void f(int a, int b, int c, int *pmax, int *pmin) 3 { 4 *pmax = *pmin = a; 5 if (*pmax > b) 6 { 7 *pmin = b; 8 } 9 if (*pmin < b) 10 { 11 *pmax = b; 12 } 13 if (*pmax > c) 14 { 15 *pmin = c; 16 } 17 if (*pmin < c) 18 { 19 *pmax = c; 20 } 21 } 22 main() 23 { 24 int a, b, c, max, min; 25 printf("input a b c=? "); 26 scanf("%d %d %d", &a, &b, &c); 27 f(a, b, c, &max, &min); 28 printf("max=%d,min=%d", max, min); 29 }