【C语言】指针基础知识超详细第一弹!

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

前言

一、指针是什么?

二、(&)取地址操作符、指针变量、(*)解引用操作符

1.(&)取地址操作符

2.  指针变量:   

 

  

三、指针变量的大小、类型、+-整数

1.指针变量的大小: 

2.指针变量的类型:

3.指针+-整数:

四、void*指针  野指针  

1.void*指针

2.野指针

2.1什么是野指针?

2.2为什么会出现野指针?

2.3怎样避免野指针?

五、const修饰指针   assret 断言   

1.const修饰指针

2.assret断言

六、指针运算

1.指针+-整数

2.指针 +-指针

七、神奇的数组名    指针访问数组   一维数组传参本质

1.神奇的数组名

2.使用指针访问数组

3.一维数组传参本质


前言

指针的重要性:

表示一些复杂的数据结构快速的传递数据,减少了内存的耗用【重点】,使函数返回一个以上的值【重点】,能直接访问硬件,能够方便的处理字符串,是理解面向对象语言中引用的基础

总结:指针是C语言的灵魂


一、指针是什么?

简单来说:   内存单元的编号 == 地址 == 指针。

复杂来说:   指针就是地址,地址就是指针。指针变量就是存放内存单元编号的变量,或者说指针变量就是存放地址的变量。指针和指针变量是两个不同的概念。但是要注意:通常我们叙述时会把指针变量简称为指针,实际它们含义并不一样。指针的本质就是一个操作受限的非负整数

二、(&)取地址操作符、指针变量、(*)解引用操作符

1.(&)取地址操作符

    (&):在C语言中,我们有时会需要获取某个变量的地址,这时取地址操作符就可以起到这个作用。

值得注意的是,&a取出的是a所占4个字节中地址较⼩的字节的地址。

虽然整型变量占⽤4个字节,我们只要知道了第⼀个字节地址,顺藤摸⽠访问到4个字节的数据也是可以的。

2.  指针变量:   
刚刚通过取地址操作符(&)拿到的地址是⼀个数值,0000000217ACFF984,这个数值有时候也是需要存储起去使用,因此指针变量就被用来存储这样的地址值。

  

3.解引用操作符  (*)

  当我们通过指针变量取得地址后,还得通过指针找到指针所指向的对象,这个时候就需要用到解引用操作符了。

所以,*p 其实就是 a 变量。

三、指针变量的大小、类型、+-整数

1.指针变量的大小: 

对于指针变量的大小我们只需要知道,

 32位平台下地址是32个bit位,指针变量大小是4个字节

 • 64位平台下地址是64个bit位,指针变量大小是8个字节
 • 注意指针变量的大小和类型是无关的,只要指针类型的变量,在相同的平台下,大小都是相同的。

2.指针变量的类型:

指针的类型决定了,对指针解引⽤的时候有多大的权限(⼀次能操作几个字节)。

比如: char* 的指针解引⽤就只能访问⼀个字节,而 int* 的指针的解引用就能访问四个字节。

3.指针+-整数:

char* 类型的指针变量+1跳过1个字节, int* 类型的指针变量+1跳过了4个字节。
这就是指针变量的类型差异带来的变化。指针的类型决定了指针向前或者向后⾛⼀步有多大(距离)

四、void*指针  野指针  

1.void*指针

void*指针可以用来接受任意类型地址。但是也有局限性, void* 类型的指针不能直接进

行指针的+-整数和解引用的运算。

2.野指针

2.1什么是野指针?
概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
2.2为什么会出现野指针?

(1)  指针未初始化(默认为随机值)

(2) 指针越界访问

(3)指针指向的空间已经被释放

2.3怎样避免野指针?
明确知道指针指向直接赋值地址。
不知道指针指向,可以给指针赋值NULL。
      注意:NULL 是C语⾔中定义的⼀个标识符常量,值是0,0也是地址,这个地址是无法使⽤的,读写该地址会报错

五、const修饰指针   assret 断言   

1.const修饰指针
const修饰变量后,就是在语法上加了限制,使得变量不能被修改。
但值得注意的是 const位于 * 的左右两边会产生不同的效果。
const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。 但是指针变量本⾝的内容可变。
const如果放在*的右边,修饰的是指针变量本⾝,保证了指针变量的内容不能修改,但是指针指向的内容,可以通过指针改变。
总结来说,就是   " 右边左不变,变的是内容。 "
2.assret断言
assert() ,⽤于在运⾏时确保程序符合指定条件,如果不符合,就报错终止运行。这个宏常常被称为“断⾔”。
assert() 宏接受⼀个表达式作为参数。如果已经确认程序没有问题,不需要再做断⾔,就#include <assert.h> 语句的前⾯,定义⼀个宏 NDEBUG
# define NDEBUG
# include <assert.h>

六、指针运算

1.指针+-整数

如果一个指针p的类型是int*,而整数n的值为2,则p - n   (p+n) 的值相当于p在内存中向后前移动了2个int类型的步长。(8个字节)

需要注意的是,指针的类型和整数的类型必须匹配。如果指针的类型是int*,而整数的类型是double,则编译器会发出警告或错误。

2.指针 +-指针

对于指针的加法操作,即将两个指针相加。这可以用于计算指针之间的偏移量。例如,如果有两个指向数组元素的指针,可以通过将它们相加来计算它们之间的距离,得到数组中的元素个数。

对于指针的减法操作,即将一个指针减去另一个指针。这可以用于计算两个指针之间的偏移量。例如,如果有两个指向数组元素的指针,可以通过将它们相减来计算它们之间的距离,得到数组中的元素个数。

七、神奇的数组名    指针访问数组   一维数组传参本质

1.神奇的数组名

数组名就是数组首元素(第⼀个元素)的地址。

但以下两种情况,数组名不是数组首元素地址

sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的大小,单位是字节
&数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素 的地址是有区别。

2.使用指针访问数组

其实跟通过指针访问整形一样。由于数组名代表数组首元素地址,所以将数

首元素地址交给指针变量p,然后通过for循环,访问数组每一个元素。

                     int * p = arr;
                     for (i= 0 ; i<sz; i++)
                    {
                          scanf ( "%d" , p+i);
                         //scanf("%d", arr+i);// 也可以这样写
                    }

本质上p[i] 是等价于 * (p + i)。

3.一维数组传参本质

⼀维数组传参,形参的部分可以写成数组的形式,也可以写成指针的形式。
void test ( int arr[])          //参数写成数组形式,本质上还是指针
{
printf ( "%d\n" , sizeof (arr));
}
void test ( int * arr)          //参数写成指针形式
{
printf ( "%d\n" , sizeof (arr)); // 计算⼀个指针变量的大小 
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值