C语言基础之指针1(基础篇)

指针计划分成3篇来讲: 上篇是指针的基本使用 、 中篇指针与数组的联系、下篇是指针与字符串的联系

一、概述

       指针其实也是变量的一种,只是它是一种特殊的变量,特殊就特殊在它所接受的值并不是简单的值,比如整数10, 小数8.5, 字符 a ,它接受的是具体的地址。这个地址可以是一个变量的地址、一个函数的地址。一旦完成指针的初始化,即可看成指针与目标地址产生了指向关系,有了这层指向关系后,后续希望获取目标地址的值,除了使用原有的变量名之外,也还可以通过指针来操作。这也就是“指针”的意思。

二、声明和初始化

2.0 说在前面话

a. 指针的声明和初始化非常简单,与普通的变量几乎无异。

b. 指针声明的语法是: 指针类型 * 指针名称 = 具体的地址;

c. 获取变量的地址,需要使用取地址符号: & 小伙伴们不要把这个符号看成是与运算了)

2.1 声明指针并初始化

#include <stdio.h>

int main(){
    // 定义一个变量 number
    int number= 10 ;
    // 声明一个int类型的指针p, 并且指向number这个变量。
    int * p = &number
    return 0 ;
}

柯南有话说:

1. number变量位于内存中有自己的地址,假设为: 0xF8

2. 使用指针p 指向 number , 相当于是在 指针 p 所开辟的内存空间里面存放 : 0xF8.

3. 当然指针p 也是一个变量,它应该也有自己的内存地址,比如此处给的: 0xCA . 但是此时没有谁指向它而已。

4. 指针的类型通常与它所指向的目标位置的数据类型一致。比如 int类型的指针指向int类型数据 ...

2.2 声明指针然后再赋值

#include <stdio.h>

int main(){
    // 1. 定义一个 int 类型的指针 【虽然看起来没有指向,但是这种写法有风险的,后续再说道】
    int * p ;

    //2. 定义一个变量 number
    int number = 10 ;

    //3. 把number的地址赋值给 p
    p = &number;
    return 0 ;
}

三、解引用

        有了指针之后,就可以使用指针来解引用,使用 解引用符号 * 来操作所指向的目标位置区域了。我们可以获取所指向位置的值,也可以修改所指向位置里面的值

#include <stdio.h>

int main(){

    // 定义一个变量 number
    int number= 10 ;

    // 使用变量赋值和取值
    number = 20;
    printf("number的值是:%d \n", number);

    // 声明一个int类型的指针p, 并且指向number这个变量。
    int * p = &number

    // 使用指针解引用赋值和取值
    *p = 30;

    printf("number的值是:%d \n", *p);
    return 0 ;

}

柯南有话说

1. 上面的代码底部的 *p = 30 。 此处的 * 符号即为 解引用符号。千万不要把 *p 和上面的 int *p 看成是一样的。

        1.1 上面的 int * p 里面的 * 表示 p 是一个指针, 此处的 * 是指针的标识

        1.2 底部的 *p 是表示要解引用,因为在这里 p 其实已经是指针了。

2. 解引用是指针的典型应用场景,甚至可以说是指针的最大作用。比如咱们平常所见到的内存修改器,背后其实就是使用指针指向具体的内存数据值,然后再利用解引用去修改值。

四、指针地址和大小

4.1 指针的地址

正如前面所说的指针也是一个变量,只是它比较特殊而已【它接收的值是地址】,既是变量,我们就可以对它取地址。其实对指针去地址对变量取地址没有什么两样。好比是我们取得教室101的地址和教室202的地址, 都是地址。区别仅仅在于教室里面装的是什么。

1. 猜一猜下面5句输出代码,分别会打印什么?

#include <stdio.h>

int main(){
    // 定义一个变量 number
    int number= 10 ;
    printf("number的值是: %d\n" , number); // 1
    printf("number的地址是: %#x\n", &number); // 2

    // 声明一个int类型的指针p, 并且指向number这个变量。
    int * p = &number;
    printf("指针p的值是: %#x\n" , p); // 3
    printf("指针p的地址是: %#x\n", &p); // 4
    printf("指针p所指向的位置存放的数据是: %d\n", *p); // 5

    return 0 ;
}

柯南有话说

1. 第一行打印语句,输出的结果很容易就可以看出来是: 10

2. 第二行打印语句,输出的结果每个人运行结果不太一样了,打印的是内存地址, 比如我的电脑打印的是:0x9fdffcf4

3. 第三行打印语句,输出的是p的值,其实就是指针指向了哪里。结果显然就是number 的地址,所以打印的是: 0x9fdffcf4

4. 第四行打印语句,输出的是指针p的地址,这个每个人运行结果不太一样了,打印的是内存地址, 比如我的电脑打印的是: 0x9fdffcf8

5. 第五行打印语句,输出的是指针p指向的目标地址存放的值,它指向的是number, 所以当然应该打印: 10

6. 在打印的时候,我们使用 %x 来打印输出十六进制地址 , 前面加上# 表示强制使用十六进制格式打印,所以打印结果前面会有 0x 打头。

4.2 指针的大小

正如前面所说的指针也是一个变量,所以它也会有占用空间大小之分。不过它倒不用像其他数据类型有这么多变化,在32位系统下指针的大小(占用空间)是4个字节,在64位系统下指针的大小(占用空间)是8个字节。其实这很好理解: 指针就是专门存放着所指向的目标位置的地址,甭管目标位置存放的是什么数据。我们的指针永远在自己的位置储存着目标的地址。

#include <stdio.h>

int main(){

    // 定义一个变量 number, 并且使用指针 p 指向它。
    int number= 10 ;
    int * p = &number;

    // 定义一个变量 c ,并且使用指针 p1 指向它
    char c = 'a';
    char * p1 = &c;

    // 定义一个变量 price , 并且使用指针 p2 指向它
    double price = 20.5;
    double * p2 = &price;


    //把这3个不同类型的指针占用大小打一下,我们会见到一样的值。
    //如果是32位的系统,那么则得到4个长度,如果是64位的系统,则得到8个长度
    printf("指针p占用空间大小: %d \n" , sizeof(p));
    printf("指针p1占用空间大小: %d \n" , sizeof(p1));
    printf("指针p2占用空间大小: %d \n" , sizeof(p2));

    return 0 ;

}

五、总结

1. 这章内容我们主要学习了指针的概念、声明和初始化、指针解引用、指针的地址和大小这些内容。 总体来说作为指针的入门学习篇,代码难度中等偏下,小伙伴们只要亲自动手写过一遍,那么还是十分容易记下来的。

2. 指针声明后应该完成初始化,或者在未初始化前不要贸然解引用。解引用应该是指针的经典应用了,小伙伴们请务必勤加练习。

3. 至于指针的地址和大小,这个应该就是套路而已,把规律记住,其实根本不需要费多大的功夫和时间。

六、思考

1. 指针声明未初始化前,不要贸然操作指针,这是出于什么考虑呢?

2. 指针可以接收地址,这样就可以指向具体的目标值了,那么请思考一下:是否可以让指针指向指针呢?

3. 指针的类型一般与所指向的目标位置数据类型保持一致,如果不一致会有什么问题?

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值