全国计算机等级考试二级教程-C语言程序设计_第8章_地址和指针

面试:

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 = &num;
10     int *p2 = &num;
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 = &num;
10     int *p2 = &num;
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 = &num;
11     p++;//指针++,就是按照指针类型的大小,前进一个类型的大小,如果是int,前进4个字节
12     printf("%d", *p);//指针++,只有在数组内部才有意义
13 
14     system("pause");
15 }

int *p1 = &num;//地址的赋值
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 = &num;//地址的赋值
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 = &num;
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 = &num;
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 = &num;

 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;//&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 }

 

原文地址:https://www.cnblogs.com/denggelin/p/5379876.html