C语言教程(八)指针

1. 简述

也许从现在开始,才真正进入C语言的世界。指针是C语言中最重要的概念之一,也是最简单的语法同时也是最难学习的语法之一。指针体现了C语言中语法的“简单、高效”特点,指针是C语言的灵魂。

指针是一个值,代表的是内存地址本身。每个内存单元都有一个唯一的地址,而指针就代表这个地址。但是指针不可以直接操作,而是要存储到指针变量中才可以使用。

指针也是一种数据类型,也可以用于声明变量保存指针,这就是指针变量。普通变量存储的是一个具体的数值,而指针变量存储的是内存地址。

2. 声明指针(变量)

指针变量可以声明为任何类型的变量,指针变量的声明由三部分组成:指针类型、指针变量名、变量值(指针)所指向的变量的数据类型,使用*符号来声明,声明形式为:类型说明符 * 变量名:

int *a;

上面示例中声明了一个变量名为a的指针变量,它存储的是int类型变量的地址,也就是说int*是一个指向int类型的值的指针,而a指向的内存地址存储的是int类型的值,

*符号可以在类型说明符和变量名之间的任意地方,都是有效合法的,就看个人规范和习惯;如果要声明多个同类型的指针变量且在同一行,那么*符号只能跟在变量名前:

//下面三种声明都是合法的
int* a;
int * a;
int *a;

//声明同类型的指针变量在同一行
int *a,*b;//正确
int *a,b;//错误,只有a是int*类型,b是整型

当然,指针变量还可以指向一个指针,也就是指针的指针,成为二级指针,也可以声明三级指针、四级指针,不过这里主要以一级指针为主:

int **a;//声明为二级指针

3. 指针变量初始化

指针变量声明后,编译器会为该指针变量分配一块内存空间,并初始化一个随机值。指针变量存储的是内存地址,所以这个随机值就是一个随机地址,如果不进行显式初始化,随便读取和写入这个内存地址是一种很危险的行为。建议将声明的指针变量先初始化为NULL,就不会指向其他地址了。

int *p;//随机地址
*p = 5;//错误
//建议设置为NULL
int *p = NULL;//地址为0,无法写入的,但不会指向随机地址了

指针变量初始化,就是要把一个地址赋值给指针变量,这个地址必须是已经分配好的内存地址,不能随意写入一个值。

int *p;//指向随机地址
int a = 5;//已经分配好内存地址了
p = &a;//&符号表示获取变量a的地址,后面会讲到

4. 取址&和取值*

&是一个地址运算符,在变量名前使用&操作符,可以获取到该变量所在的内存地址。

int a = 1;//声明普通变量
int *p = NULL;//声明普通变量,并初始化为NULL
p = &a;//将地址赋值给指针变量
printf("变量a的地址是 %p\n", &a);//%p占位符打印地址

声明变量时,*符号用于声明一个指针变量;*符号还可以作为指针的取值,从指针指向的内存地址中读取数据(值),这个操作也称为“解引用”。

int a = 5;
int *p = NULL;
p = &a;
int b = *p;//解引用,取出变量a的值
printf("变量a的地址是 %p\n", &a);//%p占位符打印地址
printf("变量b的值是 %d\n", b);//取出指针变量p指向的变量a地址存储的值

&取址运算符和*取值符是互逆运算,先取地址再解引用,和原值的值是一样的

int a = 5;
a == *(&a);//相等

5. 指针运算

指针是一个内存地址,内存地址是从0开始的,所以它是一个无符号整型数值,是可以参与运算的。虽然同样是数值,但运算规则和普通的数值不同,通常用于与整数的运算。

  • 指针与整数的运算,指针与整数相加或者相减,表示偏移n个长度的指针指向
  • 指针与指针的减法运算,返回两个指针之间相隔多少个数据单位(根据类型大小不同),高地址减低地址返回正数,低地址减高地址返回负数
  • 指针与指针的比较运算,比较两个指针哪个更大一些,返回true或者false
  • 指针与指针不能相加运算,也不能做乘除运算,否则会报错
//指针与整数相加减
int *p;
int a = 5;
p = &a;
printf("指针变量p的值是 %p\n", p);
p += 1;
printf("指针变量p的值是 %p\n", p);//p偏移了1个单位,表示指向了下一个地址

//指针与指针相减
int *p1;
int *p2;
int a = 5;
int b = 5;
p1 = &a;
p2 = &b;
printf("p1的值是 %p\n", p1);
printf("p2的值是 %p\n", p2);
printf("%td\n", p2-p1);

//指针与指针比较
if(p1 < p2){
   printf("p1小于p2");
}

上面的示例中,指针与整数计算,根据与整数的计算值来确定偏移的字节大小,比如指针变量加1,并不是在地址加1,而是偏移一个int*指针类型所占用的字节大小,也就是偏移4个字节。如果设定整数为m,以m为单位,指针变量指向的数据类型占用n个字节大小,所以偏移的字节大小就为m * n。

指针与指针的减法运算,返回的不是字节大小,而是一个以数据类型为单位的长度,比如int*类型,相隔4个字节,那就是返回1。

7. 野指针

野指针是指指针指向了一个不确定的地址,且地址值是随机的,尽量避免野指针的使用。

野指针的常见情形有下面五种:

  • 声明指针变量之后没有对它进行初始化,也没有赋值为NULL;
  • 指针所指向的变量已经被销毁,仍使用该指针访问该变量,出现运行错误;
  • 指针被free()或者delete()之后,没有赋值为NULL,此时指针指向的就是“垃圾”内存;
  • 指针指向的数组超出范围导致越界访问
  • 指针运算规则使用错误。

8. 总结

  • 指针是一个内存地址,应放在指针变量中使用;
  • 指针变量声明后必须要初始化后才能使用,或者指定为NULL,否则就是野指针;
  • 指针变量初始化必须是编译器分配好的地址,不能随意指定一个值;
  • 指针使用&符号获取变量的地址,使用*符号获取指针变量所指向地址的值,&与*是互逆运算;
  • 指针可以与整数相加减、与指针相减、与指针比较运算,但不能进行相加;
  • 应当避免野指针的使用。
觉得有帮助可以赞赏本文哦~万分感谢!
文章:C语言教程(八)指针
作者:沛旗
链接:https://www.peiqiblog.com/article/1665/
版权声明::本博客站点所有文章除特别声明外,均采用 CC BY-NC-SA 4.0协议
转载请注明文章地址及作者哦~
暂无评论

发送评论(禁止发表一切违反法律法规的敏感言论) 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇