当前位置:   article > 正文

C语言基础5指针专题一_分析下面代码,理解指针与二维数组 #include int main(){ int

分析下面代码,理解指针与二维数组 #include int main(){ int a[3][4]={1

目录

一、基本概念

1.基本用法

2.地址和变量

3.指针

指针变量的说明

指针的初始化

指针的目标

指针的赋值

总结

二、指针的运算

1.指针运算的意义

2.两指针相减运算的意义

3.指针的关系运算符

三、指针与数组

1.简述

2.数组名和指针变量

3.公式结论

四、指针与二维数组

1概念

2遍历

3行指针

4.总结


一、基本概念

1.基本用法

C程序设计中使用指针可以
-使程序简洁、经凑,高效
-有效地表示复杂的数据结构
-动态分配内存
-得到多于一个的函数返回值

2.地址和变量

地址和变量
在计算机内存中,每个字节单元,都有一个编号,称为地址。
1Byte =8bit。
看到的地址是起始地址,编译或函数调用时为其分配内存单元,变量是对程序中数据存储空间的抽象。

int a = 8;

0数据
...数据
20008
2001数据
2002数据
2003数据

3.指针

在C语言中,内存单元的地址称为指针,专门用来存放地址的变量,称为指针变量。
在不影响理解的情况中,有的对地址、指针和指针变量不区分,通称指针。

指针变量的说明

一般形式:
<存储类型> <数据类型> *<指针变量名>;
例如,auto char *pName (放的内容是char类型)
指针的存储类型是指针变量本身的存储类型。
指针说明时指定的数据类型不是指针变量本身类型,而是指针目标的数据类型。简称为指针的数据类型

指针的初始化

指针在说明的同时,也可以被赋予初值
一般形式:
<存储类型> <数据类型> *<指针变量名> = <地址量>;
例如:

int a, *pa=&a;


在上面语句中,把变量a的地址作为初值赋予了刚说明的int类型指针pa。

  1. int a =3//int a; a =3;
  2. int *pa = &a; //int *pa; pa = &a;
  1. #include <stdio.h>
  2. int main(int argc,char *argv[]){
  3. int a = 10;
  4. int *p;
  5. p = &a;
  6. printf("&p:%p %d\n", &p,sizeof(int *));
  7. printf("%p %p\n", p, &a);
  8. return 0;
  9. }
  10. &p:0xbfa9364c 4
  11. 0xbfa93648 0xbfa93648 //指针变量p的地址,就是变量a的地址;

指针的目标

指针指向的内存区域中的数据称为指针的目标
如果它指向的区域是程序中的一个变量的内存空间,则这个变量称为指针的目标变量。简称为指针的目标。

引入指针要注意程序中的px、*px和&px三种表示方法的不同意义。设px为一个指针,则:
px-指针变量,它的内容是地址量
*px-指针所指向的对象,它的内容是数据
&px-指针变量占用的存储区域的地址,是个常量

  1. #include <stdio.h>
  2. int main(int argc,char *argv[]){
  3. int a = 10;
  4. int *p;
  5. p = &a;
  6. printf("%d %d\n", a, *p);
  7. return 0;
  8. }
  9. 10 10

指针的赋值

是通过赋值运算符向指针变量送一个地址值
向一个指针变量赋值时,送的值必须是地址常量或指针变量,不能是普通的整数(除了赋零以外)

  1. //1
  2. doublx x =15, *px;
  3. px = &x; //类型相同,都是double
  4. //2
  5. float a, *px,*py;
  6. px = &a;
  7. py = px;
  8. //3
  9. int a[20],*pa;
  10. pa = a; //等价于pa

总结

什么是指针?内存以字节为单位编号,内存单元的地址称为指针,专门用来存放地址的变量,称为指针变量。
指针占几个字节?32位系统都是4个字节。

操作系统和内存有多少个地址线?32根地址线需要4G的内存,这里可以根据计算公式来得到结果,比如32根地址线的计算结果是2^32=4*1024mb=4G,所以它应该用4G内存。一般而言内存上地址线会有64个,最多支持128bit,所以无论内存多大,地址线的总数是有限制的

二、指针的运算

1.指针运算的意义

不同数据类型的两个指针实行加减整数运算是无意义的
px+n表示的实际位置的地址量是:(px)+sizeof(px的类型)*n 
px-n表示的实际位置的地址量是: (px)-sizeof(px的类型)*n

运算符计算形式意义
+px+n指针向地址大的方向移动n个数据
-px-n指针向地址小的方向移动n个数据
++px++或 ++px指针向地址大的方向移动1个数据
--

px-- 或 --px

指针向地址小的方向移动1个数据
-px-py两个指针之间相隔数据元素的个数

q先赋值,后p++ 所以还是之前的值 ,如果是++p就不一样了

  1. #include <stdio.h>
  2. int main(int argc,char *argv[]){
  3. int a[5] = {4, 8, 1, 2, 7};
  4. int *p,*q;
  5. p = a; //&a[0]
  6. printf("%p %d\n", p, *q);
  7. q = p++;
  8. printf("%p %d\n", p, *p);
  9. printf("%p %d\n", q, *q);
  10. return 0;
  11. }
  12. 0xbfa44cec -1079745597
  13. 0xbfa44cf0 8
  14. 0xbfa44cec 4 //q先赋值,后p++ 所以还是之前的值 ,如果是++p就不一样了

2.两指针相减运算的意义

px-py运算的结果是两指针指向的地址位置之间相隔数据的个数。因此,两指针相减不是两指针有的地址值相减的结果。
-两指针相减的结果值不是地址量,而是一个整数值,表示两指针之间相隔数据的个数。(一般结合数组,用的频率才高)

  1. #include <stdio.h>
  2. int main(int argc,char *argv[]){
  3. int a[5] = {4, 8, 1, 2, 7};
  4. int *p,*q;
  5. p = a;
  6. q = &a[3];
  7. printf("%p %p\n", p, q);
  8. printf("%d %d\n", *p, *q);
  9. printf("%d\n", q-p);
  10. return 0;
  11. }
  12. 0xbfdd15bc 0xbfdd15c8
  13. 4 2
  14. 3

3.指针的关系运算符

-两指针之间的关系运算表示它们指向的地址位置之间的关系。指向地址大的指针大于指向地址小的指针。
-指针与一般整数变量之间的关系运算没有意义。但可以和0进行等于或不等于的关系运算,判断指针是否为空。

>        <        >=        <=        !=        ==

  1. #include <stdio.h>
  2. int main(int argc,char *argv[]){
  3. int *p= NULL;
  4. printf("%p\n",p);
  5. return 0;
  6. }
  7. (nil)

程序举例1

第一步 --p   //指向a[0]
第二步 *--p //取地址里数据
第三部 (*--p)++// 先赋值,后数据++

  1. #include <stdio.h>
  2. int main(int argc,char *argv[]){
  3. int a[]={5,8,7,6,2,7,3};
  4. int y,*p = &a[1];
  5. y = (* --p)++;
  6. printf("%d %d",y,a[0]);
  7. }
  8. 5 6

程序举例2

指针可以代替数组下标

  1. #include <stdio.h>
  2. int main(int argc,char *argv[]){
  3. int i, *p, a[7];
  4. p = a;
  5. for(i = 0; i<7; i++)
  6. scanf("%d",p++);
  7. printf("\n");
  8. p = a;
  9. for(i = 0; i<7; i++){
  10. printf("%d",*p);
  11. p++;
  12. }
  13. }

三、指针与数组

1.简述

在C语言中,数组的指针是指数组在内存中的起始地址,数组元素的地址是指数组元素在内存中的起始地址
一维数组的数组名为一维数组的指针(起始地址)
如double x[8];x为x数组的起始地址

设指针变量px的地址值等于数组指针x(既指针变量px指向数组的首元素),则:
x[i]、*(px+i)、*(x+i)和px[i]具有完全相同的功能:访问数组第i+1个数组元素。

2.数组名和指针变量

x[i] 和 *px

x++会报错,因为是地址常量,但是x+1,x+2可以
但是指针px++可以。
虽然都是一样,但是一个是数组名是常量,一个是指针是变量

下标法:x[i]

指针法: *(px+i)

注意

指针变量和数组在访问数组中元素时,一定条件下其使用方法具有相同的形式,因为指针变量和数组名都是地址量
但指针变量和数组的指针(或叫数组名)在本质上不同,指针变量是地址变量,而数组的指针是地址常量。

程序举例

编写一个函数,将整型数组中n个数按反序存放

  1. #include <stdio.h>
  2. int main(int argc,char *argv[]){
  3. int buf[10]={0};
  4. int *p,*q,temp,n,i;
  5. n = 10;
  6. printf("please input:\n");
  7. for(i = 0; i < n; i++){
  8. scanf("%d",&buf[i]); //循环接受数字
  9. }
  10. p = buf;
  11. q = &buf[n-1];
  12. //冒泡算法
  13. while(p < q)
  14. {
  15. temp = *p;
  16. *p = *q;
  17. *q = temp;
  18. p++;
  19. q--;
  20. }
  21. }
  22. 2,1 Top

3.公式结论

a[i] <<==>>*(a+i)

四、指针与二维数组

1概念

多维数组就是具有两个或两个以上下标的数组
在c语言中,二维数组的元素连续存储,按行优先存。

2遍历

  1. #include <stdio.h>
  2. int main(int argc,char *argv[]){
  3. int a[3][2] = {{1,6},{9,12},{61,12}};
  4. int *p, i, n;
  5. n = sizeof(a) / sizeof(int);
  6. p = a;
  7. printf("%p %p\n", p, p+1);
  8. printf("%p %p\n", a, a+1);
  9. for(i = 0; i < n; i++)
  10. printf("%d ",*(p+i));
  11. puts("");
  12. return 0;
  13. }
  14. //结果
  15. 0xbfbd2c08 0xbfbd2c0c
  16. 0xbfbd2c08 0xbfbd2c10
  17. 1 6 9 12 61 12

用一级指针遍历二维数组,p = a 类型不匹配。p是1级, a是两级,改成&a[0][0] 就没警告了,也可以写p=a[0],a[0]也是数组名。a[0]++会报错,常量不能放等号左边

3行指针

二维数组名代表数组的起始地址,数组名+1,是移动一行元素。因此,二维数组名常被称为行地址

a[0]a[0][0]
a[0][1]
a[0][2]
a[1]a[1][0]
a[1][1]
a[1][2]
a[2]a[2][0]
a[2][1]
a[2][2]

行指针(数组指针)
存储行地址的指针变量,叫做行指针变量。形式如下:
-<存储类型> <数据类型> (*<指针变量名>)[表达式];
例如: int a[2][3];
           int (*p)[3];//行指针
方括号中的常量表示是表示指针加1,移动几个数据。
当用行指针操作二维数组时,表达式一般写成1行的元素个数,既列数。

程序举例:遍历二维数组,二维数组指针和行地址概念

  1. #include <stdio.h>
  2. int main(int argc,char *argv[]){
  3. int a[3][2] = {{1,6},{9,12},{61,12}};
  4. int i, j;
  5. int (*p)[2];
  6. p = a;
  7. printf("%p %p\n", a[0], a[0]+1);//
  8. printf("%p %p\n", a, a+1); //a和p是行地址指针变量
  9. printf("%p %p\n", p, p+1); //a和p是行地址指针变量
  10. printf("%d %d %d %d\n",a[1][1],p[1][1],*(*(a+1)+1),*(*(p+1)+1));
  11. //遍历二维数组
  12. for(i = 0; i < 3; i++)
  13. for(j = 0; j < 2; j++)
  14. printf("%d %d %d %d\n",a[i][j],p[i][j],*(*(a+i)+j),*(*(p+i)+j));
  15. puts("");
  16. return 0;
  17. }
  18. 0xbfe98698 0xbfe9869c //+4
  19. 0xbfe98698 0xbfe986a0 //+8
  20. 0xbfe98698 0xbfe986a0 //+8
  21. 12 12 12 12
  22. 1 1 1 1
  23. 6 6 6 6
  24. 9 9 9 9
  25. 12 12 12 12
  26. 61 61 61 61
  27. 12 12 12 12

a[0]+1   =*a +1

如果移动一行一列*(*(a+1)+1)或*(*(p+1)+1) 等于a[1][1] 或p[1][1]

4.总结

主要介绍了指针与二维数组,包括一级指针如何访问二维数组以及行指针如何访问二维数组
二维数组特点:1地址常量,地址名+1是移动一行。编程,实现二维数组遍历。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/223633
推荐阅读
相关标签
  

闽ICP备14008679号