【C语言】指针----初阶

这篇具有很好参考价值的文章主要介绍了【C语言】指针----初阶。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

💓 博客主页:江池俊的博客

⏩ 收录专栏:C语言初阶之路

🎉如果觉得博主的文章还不错的话,请点赞👍收藏🌟 三连支持一下博主💞

【C语言】指针----初阶,C语言—探索高效编程的基石,c语言,开发语言,经验分享

目录

一、指针是什么?

1.1指针与内存间的关系

内存

1.2指针变量存放地址

二、指针和指针类型

2.1指针有哪些类型?

2.2指针类型的意义是什么?

2.2.1指针的类型决定了指针向前或者向后走一步有多大(距离)。

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

 三、野指针

3.1野指针成因

3.1.1. 指针未初始化

3.1.2. 指针越界访问 

3.1.3. 指针指向的空间释放 

3.2 如何规避野指针

四、指针运算

4.1 指针+-整数

4.2 指针-指针

4.3 指针的关系运算

五、 指针和数组

六、二级指针

6.1二级指针与多级指针 

6.2二级指针运算 

七、指针数组


一、指针是什么?

在计算机科学中,指针是一种变量类型,它存储了一个内存地址。这个内存地址指向计算机内存中的一个特定位置,该位置存储了实际的数据。通过使用指针,可以直接访问和修改存储在特定内存位置的数据,而无需复制或移动数据本身。(本质上指针就是地址)

1.1指针与内存间的关系

【C语言】指针----初阶,C语言—探索高效编程的基石,c语言,开发语言,经验分享

这里我们知道char类型占1个字节的内存空间,short类型占2个字节的内存空间,int类型占4个字节的内存空间,long类型占4个字节的内存空间,long long类型占8个字节的内存空间,float类型占4个字节的内存空间,double类型占8个字节的内存空间。

内存

【C语言】指针----初阶,C语言—探索高效编程的基石,c语言,开发语言,经验分享

经过仔细的计算和权衡我们发现一个字节给一个对应的地址是比较合适的。
对于32位的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(高电压)和低电平(低电压)就是(1或者0);
那么32根地址线产生的地址就会是:
00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000001

........

01111111 11111111 11111111 11111111

10000000 00000000 00000000 00000000

10000000 00000000 00000000 00000001

........

11111111 11111111 11111111 11111110

11111111 11111111 11111111 11111111

一共有种可能的编号,每一种编号表示一个内存单元的地址,所以共有个地址。每个地址表示一个字节,那我们就可以给 (2^32Byte=2^32/1024KB=2^32/1024/1024MB=2^32/1024/1024/1024GB = 4GB)4G的空闲进行编址。
同样的方法,那64位机器,如果给64根地址线,那么就有个地址。

这里我们就明白:
🌴 在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储(因为一个字节等于八个比特位,而一个0或1占一个比特位),所以一个指针变量的大小就应该是4个字节。
🌴同理,那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。

1.2指针变量存放地址

【C语言】指针----初阶,C语言—探索高效编程的基石,c语言,开发语言,经验分享

注意:这里a的值以16进制的形式存储在内存中的并且是倒着存放的(这里涉及到大小端问题) 。

总结:指针变量是用来存放地址的变量。(存放在指针中的值都被当成地址处理)。

二、指针和指针类型

2.1指针有哪些类型?

char *pc = NULL;
int *pi = NULL;
short *ps = NULL;
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;

不同类型的指针其实是为了存放对应类型变量的地址。 

2.2指针类型的意义是什么?

2.2.1指针的类型决定了指针向前或者向后走一步有多大(距离)。

【C语言】指针----初阶,C语言—探索高效编程的基石,c语言,开发语言,经验分享

这里我们不难看出,char*类型的指针加一时,它的地址增加了1个字节,而int*类型的指针加一时,它的地址增加了4个字节 。

总结:指针变量加减 ,跳过多少字节(地址加减多少)取决于指针类型

例如:

如果是 char 类型指针,指针变量加 1或减1 实际上地址加了或减了 1 个字节

如果是 short 类型指针,指针变量加 1或减1  实际上地址加了或减了 2 个字节

如果是 int 类型指针,指针变量加 1或减1  实际上地址加了或减了 4 个字节 

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

📌char*指针

【C语言】指针----初阶,C语言—探索高效编程的基石,c语言,开发语言,经验分享

这里是将int类型的变量n的地址强制转换赋给了char类型指针pc 

【C语言】指针----初阶,C语言—探索高效编程的基石,c语言,开发语言,经验分享
指针pc解引用后:

📌int*指针 

【C语言】指针----初阶,C语言—探索高效编程的基石,c语言,开发语言,经验分享

【C语言】指针----初阶,C语言—探索高效编程的基石,c语言,开发语言,经验分享
指针pi解引用后:

 三、野指针

 概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

3.1野指针成因

3.1.1. 指针未初始化

#include <stdio.h>
int main()
{
int *p;//局部变量指针未初始化,默认为随机值
*p = 20;
return 0;
}

3.1.2. 指针越界访问 

#include <stdio.h>
int main()
{
int arr[10] = {0};
int *p = arr;
int i = 0;
for(i=0; i<=11; i++)
{
//当指针指向的范围超出数组arr的范围时,p就是野指针
*(p++) = i;
}
return 0;
}

3.1.3. 指针指向的空间释放 

动态开辟一块空间时返回的值存放到一个指针中,当使用完这个指针后没有释放时,该指针就会变为野指针。

3.2 如何规避野指针

1. 指针初始化
2. 小心指针越界
3. 指针指向空间释放即使置NULL
4. 避免返回局部变量的地址
5. 指针使用之前检查有效性

#include <stdio.h>
int main()
{
int *p = NULL;

int a = 10;
p = &a;
//检查指针的有效性
if(p != NULL)
{
*p = 20;
}
return 0;
}

四、指针运算

4.1 指针+-整数

指针加+-运算用于将指针移动指定的偏移量,以便访问其他地址处的数据。例如,如果有一个指向整型数组的指针p,可以使用p+n或p-n将指针移动n个整型长度的位置。

#define N_VALUES 5
float values[N_VALUES];
float *vp;
//指针+-整数;指针的关系运算
for (vp = &values[0]; vp < &values[N_VALUES];)
{
*vp++ = 0;
}

4.2 指针-指针

可以对两个指针进行减法运算,得到它们之间的距离(以元素个数为单位)。这在处理数组或动态内存分配时非常有用。例如,假设有两个int类型的指针ptr1和ptr2,我们可以进行如下操作:

int distance = ptr2 - ptr1; // 计算ptr2和ptr1之间的距离(以int元素个数为单位)

需要注意的是,指针运算应该谨慎使用,确保指针指向的内存是有效的。否则,可能会导致未定义行为或内存错误。此外,不同类型的指针之间不应进行直接算术运算,因为它们可能引用不同大小的数据。只有在指向同一数组的元素或有效分配的内存区域时,指针之间的运算才是有效的。 

4.3 指针的关系运算

在C、C++等编程语言中,指针的关系运算用于比较指针的地址或者判断指针是否为NULL。下面是指针的关系运算符及其含义:

📌相等(==):用于判断两个指针是否指向同一个内存地址。如果两个指针指向相同的地址,则关系表达式为真,否则为假。

int* ptr1;
int* ptr2;

if (ptr1 == ptr2) {
    // 指针ptr1和ptr2指向相同的地址
}

📌不相等(!=):用于判断两个指针是否指向不同的内存地址。如果两个指针指向不同的地址,则关系表达式为真,否则为假。

int* ptr1;
int* ptr2;

if (ptr1 != ptr2) {
    // 指针ptr1和ptr2指向不同的地址
}

📌大于(>)、小于(<)、大于等于(>=)、小于等于(<=):这些关系运算符用于比较两个指针所指向的地址之间的顺序关系。只有当指针指向同一个数组中的元素或者在有效的内存范围内时,这些关系运算符才有定义。

int* ptr1;
int* ptr2;

if (ptr1 > ptr2) {
    // ptr1指向的地址在ptr2指向的地址之后
}

if (ptr1 < ptr2) {
    // ptr1指向的地址在ptr2指向的地址之前
}

if (ptr1 >= ptr2) {
    // ptr1指向的地址在ptr2指向的地址之后或相同
}

if (ptr1 <= ptr2) {
    // ptr1指向的地址在ptr2指向的地址之前或相同
}

📌空指针检查:指针的关系运算还可以用于检查指针是否为空(指向NULL)。在C和C++中,NULL是一个预定义的宏,用于表示一个空指针。

int* ptr = NULL;

if (ptr == NULL) {
    // 指针ptr是空指针
}

if (ptr != NULL) {
    // 指针ptr不是空指针
}

需要注意的是,对于关系运算符(>, <, >=, <=),只有在指针指向同一数组的元素或有效分配的内存区域时,比较的结果才是有效的。在进行指针比较之前,最好确保指针指向的内存是有效的,否则可能会导致未定义行为。

五、 指针和数组

我们来看一个例子:

#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,0};
printf("%p\n", arr);
printf("%p\n", &arr[0]);
return 0;
}

运行结果: 

【C语言】指针----初阶,C语言—探索高效编程的基石,c语言,开发语言,经验分享

可见数组名和数组首元素的地址是一样的。
结论:数组名表示的是数组首元素的地址。(一般情况下)
那么这样写代码是可行的:

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

既然可以把数组名当成地址存放到一个指针中,我们使用指针来访问一个就成为可能。
例如:

#include <stdio.h>
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,0};
int *p = arr; //指针存放数组首元素的地址
int sz = sizeof(arr)/sizeof(arr[0]);
for(int i=0; i<sz; i++)
{
printf("&arr[%d] = %p <====> p+%d = %p\n", i, &arr[i], i, p+i);
}
return 0;
}

运行结果: 

【C语言】指针----初阶,C语言—探索高效编程的基石,c语言,开发语言,经验分享

所以 p+i 其实计算的是数组 arr 下标为i的地址。
那我们就可以直接通过指针来访问数组。
如下:

#include<stdio.h>
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int *p = arr; //指针存放数组首元素的地址
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i<sz; i++)
{
printf("%d ", *(p + i));
}
return 0;
}

运行结果: 

 【C语言】指针----初阶,C语言—探索高效编程的基石,c语言,开发语言,经验分享

六、二级指针

二级指针(double pointer)是指指向指针的指针。我们可以使用指向指针的指针来处理指针的引用或修改。它们在一些情况下非常有用,特别是在涉及到函数参数传递和动态内存分配等方面。

定义二级指针的语法为在指针类型名称前加上两个星号(**):

int** doublePtr;

6.1二级指针与多级指针 

#include<stdio.h>
int main()
{
	int a = 10;
	int* pa = &a;
	int** ppa = &pa;
	int*** pppa = &ppa;
	printf("%p\n", a);
	printf("%p\n", &a);

	printf("\n%p\n", pa);
	printf("%p\n", &pa);

	printf("\n%p\n", ppa);
	printf("%p\n", &ppa);
	
	printf("\n%p\n", pppa);
	printf("%p\n", &pppa);
	return 0;
}

【C语言】指针----初阶,C语言—探索高效编程的基石,c语言,开发语言,经验分享

【C语言】指针----初阶,C语言—探索高效编程的基石,c语言,开发语言,经验分享

6.2二级指针运算 

📌*ppa 通过对ppa中的地址进行解引用,这样找到的是 pa , *ppa 其实访问的就是 pa .

int b = 20;
*ppa = &b;//等价于 pa = &b;

📌**ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是 a .

**ppa = 30;
//等价于*pa = 30;
//等价于a = 30;

七、指针数组

指针数组是一个数组,其中的每个元素都是指针。我们可以创建指针数组来存储一组指向不同数据类型的指针。这些指针可以指向数组、字符串、函数等各种数据类型,从而实现更灵活的数据结构和操作。

定义指针数组的语法为在指针类型名称后加上方括号([]):

int* ptrArray[5]; // 定义一个包含5个int指针的数组

【C语言】指针----初阶,C语言—探索高效编程的基石,c语言,开发语言,经验分享

在上述示例中,ptrArray是一个包含5个指向int类型数据的指针的数组。我们可以通过数组下表来访问和操作这些指针:

int num1 = 10;
int num2 = 20;
int num3 = 30;

int* ptrArray[3]; // 定义一个包含3个int指针的数组

ptrArray[0] = &num1; // 第一个指针指向num1的地址
ptrArray[1] = &num2; // 第二个指针指向num2的地址
ptrArray[2] = &num3; // 第三个指针指向num3的地址

printf("Value at index 0: %d\n", *ptrArray[0]); // 输出:Value at index 0: 10
printf("Value at index 1: %d\n", *ptrArray[1]); // 输出:Value at index 1: 20
printf("Value at index 2: %d\n", *ptrArray[2]); // 输出:Value at index 2: 30

指针数组非常适用于存储字符串数组。在C语言中,字符串被表示为字符数组,并且每个字符串都以空字符('\0')结尾。使用指针数组可以更方便地管理字符串的集合:

const char* names[] = { "Alice", "Bob", "Charlie" };

在上面的示例中,我们创建了一个包含3个指针的指针数组,每个指针都指向一个字符串常量。

需要注意的是,指针数组中的每个指针应该指向有效的内存地址。否则,当我们尝试通过这些指针访问数据时,可能会导致未定义行为或者出现野指针的问题。确保在使用指针数组之前,为每个指针分配合适的内存或者让它们指向有效的数据。同时,记得在不再需要这些指针数组时,及时释放其所指向的内存,避免内存泄漏。

🔥今天的分享就到这里,如果觉得博主的文章还不错的话,请👍三连支持一下博主哦🤞

 【C语言】指针----初阶,C语言—探索高效编程的基石,c语言,开发语言,经验分享文章来源地址https://www.toymoban.com/news/detail-610417.html

到了这里,关于【C语言】指针----初阶的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言】指针初阶

     哈喽,大家好,今天我们来学习C语言中的指针,今天主要学习初阶指针,后期我们将继续学习指针进阶。 目录 1. 指针是什么 2. 指针和指针类型 2.1 指针+-整数 2.2 指针的解引用 3. 野指针 3.1 野指针成因 3.2 如何规避野指针 4. 指针运算 4.1 指针+-整数 4.2 指针-指针 4.3 指针的关

    2024年02月09日
    浏览(31)
  • C语言——指针初阶

     哈喽,大家好,今天我们来学习C语言中的指针,今天主要学习初阶指针,后期我们将继续学习指针进阶。 目录 1. 指针是什么 2. 指针和指针类型 2.1 指针+-整数 2.2 指针的解引用 3. 野指针 3.1 野指针成因 3.2 如何规避野指针 4. 指针运算 4.1 指针+-整数 4.2 指针-指针 4.3 指针的关

    2024年02月05日
    浏览(70)
  • C语言——指针详解(初阶)

    在C语言学习过程中,指针算一个难点。我总结所学的指针知识,写一篇博客,希望大家对指针的知识理解的更通透。 每个内存都有一个唯一的编号,这个编号也被称为地址,C语言创建变量。都要在内存上开辟空间。 编号= = 地址 = =指针 我们可以通过(取地址操作符)取出变

    2024年02月16日
    浏览(30)
  • C语言指针(初阶)

    嘻嘻,家人们,今天咱们剖析一下指针,好啦,废话不多讲,开干! 假设有一栋宿舍楼,把uu们放在楼里面,楼上有100个房间,但是房间没有编号,此时如果uu们的朋友来找uu们玩的话,就得挨个房间去找,这样子的话,效率很低,但是如果我们根据每个楼层与楼层的放假情况,给每个房间进行编号

    2024年02月20日
    浏览(33)
  • 【C语言】指针----初阶

    💓 博客主页:江池俊的博客 ⏩ 收录专栏:C语言初阶之路 🎉如果觉得博主的文章还不错的话,请点赞👍收藏🌟 三连支持一下博主💞 目录 一、指针是什么? 1.1指针与内存间的关系 内存 1.2指针变量存放地址 二、指针和指针类型 2.1指针有哪些类型? 2.2指针类型的意义是

    2024年02月15日
    浏览(26)
  • 【C语言】初阶指针

    指针是一种用来存储变量地址的变量类型。它可以指向任何数据类型,包括基本数据类型(如整数、字符等)和复合数据类型(如数组、结构体等)。通过指针,我们可以间接地访问或修改存储在特定内存地址上的数据。 指针是内存中一个最小单元的编号,也就是地址。 平

    2024年02月12日
    浏览(25)
  • 初阶C语言——指针

    Hello,我们又见面了,时间过的好快啊,转眼间也已经写了这么多份博客了,在接下来的一年里,小编也会认真学习的敲代码,我们一起进步,那今天开始讲我们的指针,指针这一章节在C语言的学习中是比较难的一章节,废话不多说,开始我们的学习吧。 1. 指针是什么? 指

    2024年02月13日
    浏览(31)
  • c语言初阶指针

    目录 何为指针 地址大小 野指针 成因   如何规避  有效性 指针计算 +-整数 ​编辑  指针比较运算 指针-指针 ​编辑 数组与指针关系 二级指针 指针数组 应用  指针就是 指针变量 ,用来存放内存空间的一个编号,将指针比作我们宾馆的客人,内存空间就是一个个的房间,

    2024年02月09日
    浏览(31)
  • 【初阶C语言】指针的妙用

    前言:在C语言中,有一个非常重要的知识点,叫做指针,指针也是数据类型中的一种。在本节内容中,我们就一起来学习指针。  学习一个新知识的时候,我们需要从这几个方面: 指针是什么,指针是怎么访问数据(指针是怎么工作的),也就是弄清楚指针类型的作用,怎

    2024年02月14日
    浏览(26)
  • 【C/C++】C语言开发者必读:迈向C++的高效编程之旅

    🧑 作者简介 :阿里巴巴嵌入式技术专家,深耕嵌入式+人工智能领域,具备多年的嵌入式硬件产品研发管理经验。 📒 博客介绍 :分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导、简历面试辅导、技术架构设计优化、开发外包等

    2024年03月20日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包