C语言基础5指针专题一

目录

一、基本概念

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。

int a =3;           //int a; a =3;
int *pa = &a;       //int *pa; pa = &a;
#include <stdio.h>

int main(int argc,char *argv[]){
    int a = 10;
    int *p;

    p = &a;

    printf("&p:%p %d\n", &p,sizeof(int *));
    printf("%p %p\n", p, &a);
    return 0;
}     


&p:0xbfa9364c 4       
0xbfa93648 0xbfa93648  //指针变量p的地址,就是变量a的地址;

指针的目标

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

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

#include <stdio.h>

int main(int argc,char *argv[]){
    int a = 10;
    int *p;

    p = &a;
    printf("%d %d\n", a, *p);
    return 0;
}


10 10

指针的赋值

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

//1
doublx x =15, *px;
px = &x;              //类型相同,都是double
//2
float a, *px,*py;
px = &a;
py = px;
//3
int a[20],*pa;
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就不一样了

#include <stdio.h>

int main(int argc,char *argv[]){
    int a[5] = {4, 8, 1, 2, 7};
    int *p,*q;

    p = a;    //&a[0]
    printf("%p %d\n", p, *q);
    q = p++;
    printf("%p %d\n", p, *p);
    printf("%p %d\n", q, *q);
      
    return 0;
}

0xbfa44cec -1079745597
0xbfa44cf0 8
0xbfa44cec 4   //q先赋值,后p++ 所以还是之前的值 ,如果是++p就不一样了

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

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

#include <stdio.h>

int main(int argc,char *argv[]){
    int a[5] = {4, 8, 1, 2, 7};
    int *p,*q;

    p = a;
    q = &a[3];
    printf("%p %p\n", p, q);
    printf("%d %d\n", *p, *q);
    printf("%d\n", q-p);
      
    return 0;
}

0xbfdd15bc 0xbfdd15c8
4 2
3

3.指针的关系运算符

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

>        <        >=        <=        !=        ==

#include <stdio.h>

int main(int argc,char *argv[]){

    int *p= NULL; 
    printf("%p\n",p);    
    return 0;
}

(nil)

程序举例1

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

#include <stdio.h>

int main(int argc,char *argv[]){

    int a[]={5,8,7,6,2,7,3};
    int y,*p = &a[1];

    y = (* --p)++;

    printf("%d %d",y,a[0]);
}

5 6

程序举例2

指针可以代替数组下标

#include <stdio.h>

int main(int argc,char *argv[]){
    int i, *p, a[7]; 
    p = a;
    for(i = 0; i<7; i++)
        scanf("%d",p++);
    printf("\n");

    p = a;
    for(i = 0; i<7; i++){
        printf("%d",*p);
        p++;
    }
}   
            

三、指针与数组

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个数按反序存放

#include <stdio.h>

int main(int argc,char *argv[]){
    int buf[10]={0};
    int *p,*q,temp,n,i;
    n  = 10;
    printf("please input:\n");
    for(i = 0; i < n; i++){
        scanf("%d",&buf[i]);   //循环接受数字
    }
    p = buf;
    q = &buf[n-1];

    //冒泡算法
    while(p < q)
    {
        temp = *p;
        *p = *q;
        *q = temp;
        p++;
        q--;
    }
}
                                                              2,1           Top

3.公式结论

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

四、指针与二维数组

1概念

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

2遍历

#include <stdio.h>

int main(int argc,char *argv[]){

    int a[3][2] = {{1,6},{9,12},{61,12}};
    int *p, i, n;

    n = sizeof(a) / sizeof(int);

    p = a;
    printf("%p %p\n", p, p+1);
    printf("%p %p\n", a, a+1);

    for(i = 0; i < n; i++)
        printf("%d ",*(p+i));
    puts("");

    return 0;
}

//结果
0xbfbd2c08 0xbfbd2c0c
0xbfbd2c08 0xbfbd2c10
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行的元素个数,既列数。

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

#include <stdio.h>

int main(int argc,char *argv[]){

    int a[3][2] = {{1,6},{9,12},{61,12}};
    int i, j;
    int (*p)[2];

    p = a;  

    printf("%p %p\n", a[0], a[0]+1);//
    printf("%p %p\n", a, a+1);      //a和p是行地址指针变量
    printf("%p %p\n", p, p+1);      //a和p是行地址指针变量
    printf("%d %d %d %d\n",a[1][1],p[1][1],*(*(a+1)+1),*(*(p+1)+1));

    //遍历二维数组
    for(i = 0; i < 3; i++)
        for(j = 0; j < 2; j++)
            printf("%d %d %d %d\n",a[i][j],p[i][j],*(*(a+i)+j),*(*(p+i)+j));
    puts("");

    return 0;
}

0xbfe98698 0xbfe9869c   //+4
0xbfe98698 0xbfe986a0   //+8
0xbfe98698 0xbfe986a0   //+8
12 12 12 12
1 1 1 1
6 6 6 6
9 9 9 9
12 12 12 12
61 61 61 61
12 12 12 12

a[0]+1   =*a +1

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

4.总结

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

4IOT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值