C语言指针学生笔记|“朝闻道”知识分享大赛

2301_80948168 2024-10-31 18:32:51

这是我参加朝闻道知识分享大赛的第八篇文章


C语言指针学生笔记

一、指针的基本概念

在计算机科学中,指针是编程语言的一个对象,利用地址,它的值直接指向存在于电脑存储器中的另一个地方的值。简单来说,指针就是通过它能找到以它为地址的存储单元。在计算机内存中,每一个存储单元(字节)都有自己的位置编号,即内存地址,就如同地球上的每一片土地都有自己的经纬度。

在C程序中,每一个操作对象(object)也有自己的位置编号。C程序创建、销毁、访问和操作对象。这些对象由声明、分配函数、字符串文字、复合文字以及返回结构或与数组成员联合的非左值表达式创建。在寻常意义上,一般称此为变量,变量名(标识符)起到映射内存地址的作用。

指针式内存中一个最小单元的编号,也就是地址。平时所说的指针,通常指的就是指针变量,用来存放内存地址的变量。指针的大小在32位平台是4个字节,在64位平台是8个字节。

二、指针和指针类型

指针变量的大小决定了它能存储多大的地址。对于32位的机器,假设有32根地址线,而每根地址线能产生高电压(1)和低电压(0),那么32根地址线就能产生2^32个0/1二进制序列。每个编号占用32个比特位,即4个字节。指针变量的大小在32位平台是4个字节,在64位平台是8个字节。

指针的类型决定了指针在解引用时访问的权限有多大(一次能操作几个字节)。例如:

  • char*的指针解引用访问1个字节。
  • float*的指针解引用访问4个字节。

指针的类型也决定了指针向前向后走一步有多大(+/-整数时跨越几个字节)。例如:

  • char*的指针+1,跳过1个字节。
  • int*的指针+1,跳过4个字节。

无具体类型指针(泛型指针),可以接受任意类型的地址。void*类型的指针就是无具体类型的指针,它不能直接进行解引用和指针+-整数的运算,但一般使用在函数参数的部分,用来接收不同类型数据的地址,这样的设计可实现泛型编程的效果,使用一个函数来处理多种类型的数据。

const修饰指针:

  • int *p;:无const修饰。
  • const放在*的左边,修饰的是指针指向的内容,使指针指向的内容不能通过指针来改变,但是指针变量本身的内容可以变,即指针变量存放的地址是可以改变的。
  • const放在*的右边,修饰的是指针变量本身,使指针变量的内容不能改变,即该指针变量只能存放一个固定变量的地址,但是指针指向的内容,可以通过指针来改变。
  • *的左右两边都有const,此时指针变量的内容不能改变,指针变量指向的内容也不能改变。

三、野指针

野指针就是未初始化的指针,即指向的位置不可知(随机的、不正确、没有明确限制的)。野指针的成因主要有以下几种:

  • 指针未初始化
    int main() { 
    int *pa; 
    *pa = 20; // 在未初始化的指针,其中的值也是随机,程序不会正常执行。 
    printf("%d", *pa); 
    return 0; 
    }

     

  • 指针的越界访问

指针指向的空间不合理,比如一个10个元素整型的数组,访问第11个元素的整型值,那么第十一个元素的值就是随机值。

int main() { 
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 
int *pa = arr; 
int i = 0; 
for (i = 0; i <= 10; i++) { 
printf("%d ", *pa); 
pa++; 
} 
return 0; 
}
  • 指针指向的释放空间

子函数中局部变量的内存在return之后就已经返还给内存了,再次访问的就是野指针。

int* test() { 
int a = 10; 
return &a; 
} 


int main() { 
int *pa = test(); 
printf("%d\n", *pa); 
return 0; 
}

 

  • 如何规避野指针:
  1. 指针初始化:如果明确知道指针指向哪里就直接赋值地址,如果不知道可赋值NULL
  2. 小心指针越界
  3. 指针指向空间释放即使置NULL
  4. 指针使用之前检查有效性:只要是NULL指针就不去访问,同时使用指针之前可以判断指针是否为NULL

四、指针运算

指针的运算包括:指针+-整数、指针-指针、指针的关系运算(指针的大小比较)。

  • 指针+-整数
float arr[5] = {1.0, 2.0, 3.0, 4.0, 5.0}; 
float *pa = &arr[0]; 
for (pa = &arr[0]; pa < &arr[5];) { 
*pa++ = 0; // 将数组arr中的元素全部置0。 
}
  • 指针-指针:得到的是两个指针之间的元素个数的绝对值。
int main() { 
int arr[10] = {0}; 
printf("%d", &arr[9] - &arr[0]); 
return 0; 
}

得出的结果是9,反过来是-9。

五、指针和数组

数组名表示的是数组首元素的地址。p+i计算的是数组arr[i]的地址。因此可以通过指针来访问数组。

int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 
int *p = arr; // 指针p存放数组arr首元素的地址


通过指针+-整数就可以实现对数组每个元素的访问。

六、二级指针

凡是变量就有地址,而指针变量也是变量,因此也有地址,这个地址可以用二级指针来存放,即存放指针变量的地址的二级指针变量。

int a = 0; 
int *pa = &a; 
int **ppa = &pa;


*ppa通过对ppa中存放的地址(即pa的地址)解引用,访问pa**ppa通过对*ppa中存放的地址(对ppa解引用得到pa的内容,而pa的内容是a的地址)解引用,访问a。即先通过*ppa找到pa,然后对pa解引用*pa,找到a

七、字符指针

字符指针有两种使用方式:

  • char ch = 'a';
  • const char *pc = "hello world"; // 常量字符串直接赋值给字符指针变量,常量字符串的值不能被改变,因此加一个const更好。

直接把一个常量字符串放到字符指针中,实质上是将字符串首字符的地址存放到字符指针pc中。

八、指针数组

指针数组是存放指针的数组。

int arr1[5]; // 存放了5个整型变量的数组 
char arr2[5]; // 存放了5个字符型变量的数组 
int *arr3[5]; // 存放了5个指针变量的数组

九、数组指针

数组指针存放数组的地址的指针,指向的是数组。

int arr[5]; 
int (*p)[5] = &arr;


数组指针和指针数组的区别:

  • 指针数组是一个数组,类型为数组存放的元素的类型。例如:int *arr[5]; // arr[5]是一个数组,数组的类型为int*[5],数组的元素是指针,而且是指向整型的指针变量。
  • 数组指针是一个指针,指针指向的内容是一个数组。例如:int (*parr2)[10] = &arr; // parr2是数组指针,该指针指向的是一个数组,该数组有10个元素,每个元素是int类型的。

十、函数指针

函数指针是指向函数的指针,可以用来存储函数的地址。通过函数指针,可以间接地调用函数。

函数指针的定义:

返回类型 (*指针变量名)(参数类型);


例如:

int (*func_ptr)(int, int); // 定义一个指向返回类型为int,接受两个int参数的函数的指针

函数指针的赋值:

int add(int a, int b) { 
return a + b; 
} 


int main() { 
int (*func_ptr)(int, int); 
func_ptr = add; // 将add函数的地址赋值给

 

...全文
6 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

964

社区成员

发帖
与我相关
我的任务
社区描述
中南民族大学CSDN高校俱乐部聚焦校内IT技术爱好者,通过构建系统化的内容和运营体系,旨在将中南民族大学CSDN社区变成校内最大的技术交流沟通平台。
经验分享 高校 湖北省·武汉市
社区管理员
  • c_university_1575
  • WhiteGlint666
  • wzh_scuec
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

欢迎各位加入中南民族大学&&CSDN高校俱乐部社区(官方QQ群:908527260),成为CSDN高校俱乐部的成员具体步骤(必填),填写如下表单,表单链接如下:
人才储备数据库及线上礼品发放表单邀请人吴钟昊:https://ddz.red/CSDN
CSDN高校俱乐部是给大家提供技术分享交流的平台,会不定期的给大家分享CSDN方面的相关比赛以及活动或实习报名链接,希望大家一起努力加油!共同建设中南民族大学良好的技术知识分享社区。

注意:

1.社区成员不得在社区发布违反社会主义核心价值观的言论。

2.社区成员不得在社区内谈及政治敏感话题。

3.该社区为知识分享的平台,可以相互探讨、交流学习经验,尽量不在社区谈论其他无关话题。

试试用AI创作助手写篇文章吧