C语言基础04-指针



‌基础概念

1.直接访问与间接访问

通过变量名访问该内存单元值称为对变量的“直接访问”

通过指针变量访问某内存单元值称为对变量的“间接访问“

2.类型标识符(如int)与变量标识符(*)

Elemtype * 指针变量名

(1)类型标识符Elemtype
也叫指针类型
表示指针变量 所指向的变量/所指向的内存空间存放的变量 的数据类型,称为指针变量的基类型

(2)变量标识符 *
* 表示这是定义一个指针变量

(3)变量名即为定义的指针变量名


例如: int * p;

表示p是一个指向整型变量的指针变量,
通过p可以存取一个整型变量。
像使用其他变量一样,可以对p赋值,只是对p所赋予的值只能是地址(用地址变量赋值)。


3.p(地址/指针变量)与*p(基类型值)

(1)p是指针/地址 变量(是个存着地址的变量),其值是(p中存放的)一个变量的地址。

           p收到了(放入了)哪个变量的地址,就指向哪个变量。该变量成为p的对象。

(2)*p 是p所指向的对象的值。

类型由定义变量时的类型标识符确定(如int)
→ *p是一个值,为指向变量的值


(3)* 后面只能跟地址(变量)。 *p 表示参数的值

&后面只能跟变量。 &a 表示参数a的地址


(4) ’=‘ 是赋值,默认只允许同类型的参数进行赋值(若不同类也会赋值,但是执行结果会出错)

→只允许,(指针)地址 赋值 给(指针)地址

(变量)值 赋值 给(变量)值


定义指针变量

不赋值

定义基类型指针 Elemtype *elem;

(Elemtype 是指针所指向单元内容的类型)

定义不赋值与定义空指针的区别
int *p; p随机指向一个地址数字
int *p 初始化,是一个野指针。p保存的是一个随机值(有相应的内存空间)


C、C++中NULL默认宏替换为0。用NULL来初始化指针,避免野指针。

int *p=NULL 就是指向一个空指针。值为0,有相应的地址
等同于 int *p=0 ⇒ int *p;p=NULL;

char *p=NULL 就是指向一个空指针。值为(NULL),有相应的地址

赋值

1)定义时赋值

int *p ⇔ p(读作地址变量)
int *p = &a(√)
p存放的地址初始化为&a
 
★★★定义即int *p时理解成基地址 需要赋值一个地址变量, 因为指针p没有指向变量,需要先赋值一个地址

相当于 int *p,p=&a;

2)定义后再赋值

int *p,p=&a;

定义以后的*p是一个值,需要赋值 一个实值


3)错误赋值

①定义时赋值

int *p = a; ×

不可将值(整形变量)赋值给地址(变量)

相当于int *p;p=k;(×)

②整形变量(相互)赋值地址变量 ×

int a=&p; ×

4)有关指针的赋值总结

&k,p 是地址(变量)  *p是基类型变量(如整型变量)

int *p,*q,a=20;


①*p=a; √ 给p指针指向的(地址)单元 赋值

(都是值,实现将*p指向的变量值赋值为a)

②q=p;√        因为p/q都是指针(变量),该语句实现将p的值赋值给q

③p=q=&a;√(p/q(值)是地址,&a也是地址)

④p=*q;× p=a; ×(p是地址,*q,a是值)

⑤a=*p; p=q; √(都是值)


取值(结构体类型指针):

若定义一个指针指向特定数据类型变量

如elm *p=stu1;

(等同于elem *p;p=&stu1;)

则stu1.name等同于(*p).name

又等同于p→name :p所指结构体变量(结点)的name成员(值)


数组指针与字符型指针

注意:C语言中没有特定的字符串类型,我们通常是将字符串放在一个字符数组中


1.数组指针(数组的指针)

数组指针(数组的指针 即数组被个指针指向,指针中存放的是数组的基地址)

当一个指针变量被初始化成数组名时,就说该指针变量指向了该数组(p中存放str的首地址)

如 char str[20], *p; p=str;

可以改变数组的字符值(可写)


‌2.指向字符型指针(字符型指针指向一个常量字符串)


char * str = "I love China!";

或 (*位置任意 只要在中间就行)

char * str; str = “I love China!”;

指向的一个固定常量字符串(第一个字符的地址即字符串的首地址) 不可写仅可读

对字符型指针str做输入字符串的命令,就会将常量字符串全部输出。(打印完第一个字符会自动打印完整个字符串)


3.数组指针与字符型指针声明总结

char *p(定义一个字符型指针)

(2)①p=数组名;(将数组的地址/也就是首地址 赋值 给数组指针)

p=字符串;(将字符串的地址/也就是首字符的地址 赋值 给字符型指针)

不可以把一个字符串直接赋给字符型数组的数组名



4.数组与指向字符串指针的取值

*(p+i), p[i]都是第(i+1)个元素的值

因为p是数组首地址,即p==&p[0];

⇒p是地址变量,存放数组基址


(顺序表数组指针L.elem,L.elem存放数组空间基地址)

L.elem+L.length-1 / &L.elem[L.length-1]

是最后一个(表尾)元素的地址



指针的输出(C和C++):

‌★★★C/C++指针的不同

输出

printf(“%s”,p); →输出字符串(p指向的字符串)

printf(“%d”,p); →输出指针p值

C++

输出:

cout *p →输出字符串(指针指向的内存空间)

cout p →输出指针中存放的地址


函数指针:

1‌.概念

函数有其存放的内存地方,函数名即为函数内存的首地址(地址变量)
函数指针就是指向函数的指针变量。

2.使用:

(1)函数指针的声明:

(1-1)声明:
函数返回值类型 (* 指针变量名) (函数参数列表);
Status(*p)(int)

(1-2)“函数参数列表”:该指针变量指向 具有什么参数列表的函数。
这个参数列表中只需要写函数的参数类型即可

(1-3)指针的类型:
Status(*)(int)
参数(类型)为int,返回值(类型)为Status的函数指针类型

(1-4)实例:
Status(*p)(int) 定义了一个参数(类型)为int,返回值(类型)为Status的函数指针类型 变量p

(* p)为了保证优先级

(2)赋值:

函数指针名=指向函数名;
p=add;

(函数名即为函数内存空间的首地址,看作地址变量)

也可以直接定义:
函数返回值类型 (* 指针变量名) (函数参数列表)=函数名
void (*p1)(int , int ) = add;

注意,函数void add(int a,int b)的函数名add就是函数的地址。将地址add赋值给指针p1,那么就可以通过函数指针p1直接调用函数了。


(3)调用:

(*p1)(1, 2);
p1(1, 2);

注意!出于历史原因以上2种方式都可以调用

3.原理

函数要执行的命令和普通的变量一样都是放在内存中的,既然放在内存中就会有地址

函数开始的第一条命令也不例外,而它的地址就叫函数的起始地址

现在用一个指针指向这个地址,当间接访问这个指针指向的地址所存放的命令时,这个函数就被启动了


而这个指针就叫函数指针,“函数指针”其实就是“函数的指针”


“指针函数”就是一类函数。什么类呢?是返回值是指针的函数

数组定义

char ss[]=“hello”;正确
在声明数组变量的时候为其开辟空间,并为其初始化(首地址)

char s[20];s=“hello”;错误
s的首地址在声明时已经确定,无法更改为字符串的首地址
不可以把一个字符串直接赋给字符型数组的数组名

int *p="hello";正确
把字符串的首地址赋值给地址变量p
上述语句实际等同于
int * p;p="hello";

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值