C语言------指针

一、指针的理解与定义

1.1变量的访问方式

计算面中程序的运行都是在内存中进行的,变量也是内存中分配的空间,且不同类型的变量占用不同大小的空间。那如何问内存中变量存储的数据呢?有两种方式:直接访问和间接访问。

直接访问:直接使用变量名进行的访问,以前的程序都是采用这种方式。

int num1=10;

int num2=20;

int num3=num1+num2; 

间接访问:通过指针来实现。下面看如何理解指针。 

1.2内存地址与指针

在计算机内存中,每个存储单元都有一个唯一的地址(内存编号)。

通俗理解,内存就是房间,地址就是门牌号

 

通过地址能找到所需的变量单元,可以说, 地址指向该变量单元,将 地址形象化地称为“指针”。                                                                                                                                          1. 变量:命名的内存空间,用于存放各种类型的数据。                                                            2. 变量名:变量名是给内存空间取一个容易记忆的名字。                                                        3. 变量值:在变量单元中的存放的数据值。                                                                              4. 变量的地址:变量所使用的内存空间的地址,即指针。

 

1.3指针和指针变量

1.指针是一种特殊的变量类型,它用于存储内存地址。

        指针的实质就是内存“地址”

2.指针变量就是存储这个地址的变量。 

指针变量:一个变量专门用来存放另一个变量的内存中数据的地址(即指针),则它称为“指针变量”。我们可以通过访问指针变量达到访问内存中另一个变量数据的目的。(有时为了阐述方便,将指针变量直接说成指针)

 上图中 地址:0X2000 是变量i_pointer就是一个指针变量。

体会:指针就是内存地址,使用指针访问变量,就是直接对内存地址中的数据进行操作。

指针的作用:可间接修改变量的值 

1.4指针变量的定义

1.指针也是一种数据类型,其类型是指针指向的内存空间的数据类型,指针变量也是一种变量,用来存储地址的变量。

 语法格式:

数据类型 *指针变量名[=初始地址值]

1.数据类型 是指变量所指向变量数据类型。可以是int、char、float等基本类型,也可以是数据等构造类型。(变量)

2.字符*用于告知系统这里定义的是一个指针变量,通常跟在类型关键字的后面。(指针变量)

比如,char*表示一个指向字符的指针,float*表示一个指向float类型的值的指针。

此外,还有指向数组的指针、指向结构体的指针。 

int num=10;
//-----------
int  * p ;// 读作  :指向 int 的指针  或简称  int 指针
//int  * p ;
//int*  p ;
  p=#
  p=num;// 错误的
  
//两个都是指针变量,不正确的定义

int *p1,p2;

 注意:1.指针变量的名字是p,不是*p

            2.指针变量中只能存放地址,不要将一个整数(或任何其它非地址类型的数据)赋值给一个指针变量。

1.5 const修饰的指针变量

 语法格式:

int a=1;

const int*p1=&a;          //等价于int const*p1=&a;

int *const p2=&a;

-------------------------------------------------------------------------------------------------------------------------

1.从左往右看,跳过类型,看修饰那个字符

2.如果是*,说明指针指向的值不能修改

3.如果是指针变量,指针变量的指向不能改

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
    //const修饰的指针变量
    int a = 10;
    //指针指向的内存的值不能直接修改
    const int* p = &a;  //p可以改  *p不可以改
    int b = 90;
    p = &b;
    //*p = 900;  //不能修改
    printf("%d\n", *p);

    //p2不能改  *p2可以改
    int* const p2 = &a;
    int c = 33;
    //p2 = &c;//不行
    *p2 = 777;//可以

    //p3   *p3都不能修改
    const int* const p3 = &a;
    return 0;

}

1.6应用场景

场景1:使用指针访问变量或数组的元素。

场景2:应用在数据结构中。 

二、指针的运算

指针作为一种特殊的类型可以参与运算,但与其他数据类型不同的是,指针的运算都是针对内存中的地址来实现的。

 普通变量定义:

        类型 变量;

指针变量定义:

        类型 *指针变量=&变量

        1.&叫取地址,返回操作数的内存地址

        2.*叫解引用,指 操作指针所指向的变量的值

        3.在定义变量时,*号表示所声明的变量为指针类型

                (1)指针变量要保存某个变量的地址,指针变量的类型比这个变量的一个类型多一个*

        4.在指针使用时,*号表示操作指针所指向的内存空间

2.1取址运算符:&

取值运算符,使用“&”符号来表示。

作用:取出指定变量在内存中的地址。

语法:&变量

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
    //定义一个变量  同时赋值为10
    int num = 10;
    //变量的本质:当定义一个变量时,实际上向内存申请了一块空间用来存放值
    //而每一个存储单元(byte),都有一个唯一的编号,叫做内存地址
    
    //打印输出变量的地址  也就是变量所占内存的起始地址
    printf("%p\n", &num); //00000012B44FF6B4

-------------------------------------------------
    //定义一个指针变量 保存int a的地址
    int* p;//定义了一个指针变量p
    p = &num;//指针指向了a的地址   
    //p就是指针变量,指向了a的地址  *p就是a的值
    printf("%d\n", *p);
    printf("%p\n", p);

    return 0;

}

注意:

1.在输出取址 运算获得的地址时,需要使用“%p”作为格式输出符

2.这里num的4个字节,每个字节都有地址,取出的第一个字节的地址(较小的地址)。 

指针变量赋值

指针变量中只能存放地址 (指针),不要将一个整数(或任何其它非地址类型的数据)赋值给一个指针变量

C语言中的地址包括位置信息(内存编号,或称纯地址)和它所指向的数据的类型信息,即它是 ”带类型的地址“。

所以,一个指针变量只能指向同一个类型的变量,不能抛开类型随意赋值。

如: char *类型的指针是为了存放char类型变量的地址

3.在没有对指针变量赋值时,指针变量的值是不确定的,可以系统会分配一个未知的地址,此时使用此指针变量可能会导致

不可预料的后果甚至是系统崩溃。为了避免这个问题,通常给指针变量赋初值为0(或NULL),并把值为0的指针变量称为空指针变量。

重点理解 

1.指针变量指向谁,就把谁的地址赋值给指针变量

2.通过*指针变量 间接修改变量的值

 

2.2取址运算符:*

在C语言中针对运算还提供了一个取值运算符,使用“*”符号表示。其作用与&相反,根据一个给定的内存地址取出该地址对应变量的值。也称为解引用符号

int main(){
    int a=2024;
    int *p;
    p=&a;
    
    printf("%p\n",&a); //地址
    printf("%p\n",p);、//地址
     printf("%p\n",*p);//2024
     --------
     printf("*&a=%d\n",*&num)// 2024
     
    //--------------------------------------------------
      //通过指针间接修改变量的值
        int num = 10;
    int* p = &um;//定义一个指针p 指向num的地址
    *p = 20;//通过指针间接修改a的值
    printf("%d\n", 20);//20
}

 

问题1:&*p的含义是什么?

  • & 和 * 两个运算符的优先级别相同,但按自右而左方向运算。因此, &*p 与&a相同,即变量a的地址。
  • 如果有p1= &*p; 它的作用是将&a(a的地址)赋给p1, 如果p1原来指向b,经过重新赋值后它已不再指向b了,而指向了a

问题2:*&a的含义是什么?

 先进行&a运算,得a的地址,再进行*运算。 *&a和* p的作用是一样的,它们都等价于变量a。

即 *&a 与a等价。

 2.3指针的常用运算

指针本质上就是一个无符号整数,代表了内存地址。除了取址和取值 运算外,指针还可以与整数加减、自增自减、同类指针相减运算等。但是规则并不是整数的运算

格式: 指针 + (-) 整数

指针与整数的加减运算,表示指针所指向的内存地址和移动(加,向后移动; 减,向前移动)。指针移动的单位,与指针指向的数据类型有关。 数据类型占据多少个字节,每单位就移动多少个字节。

2.3.1指针步长

指针步长指的是通过指针进行递增或递减操作时,指针所指向的内存地址相对于当前地址的偏移量。

●指针的步长取决于所指向的数据类型。

○指针加n等于指针地址加上 n 个 sizeof(type) 的长度

○指针减n等于指针地址减去 n 个 sizeof(type) 的长度

  • 50
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值