首页 > 其他分享 >初识指针

初识指针

时间:2023-01-06 10:01:01浏览次数:40  
标签:arr return int 初识 数组 main 指针

  • 指针是什么
  • 指针和指针类型
  • 野指针
  • 指针运算
  • 指针和数组
  • 二级指针
  • 指针数组

自学b站“鹏哥C语言”笔记。

一、指针是什么

指针是编程语言中的一个对象,利用地址,它的值直接指向存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”,意思是通过它能找到以它为地址的内存单元。

总结:指针是个变量,存放内存单位的地址(编号)。存放在指针中的值都被当成地址处理。

int main()
{
int a = 10;
int* p = &a;//指针变量p
return 0;
}

问题1:一个小的单元有多大?

答:1个字节。

问题2:如何编址?

答:每个地址标识一个字节。对于32位的机器,假设有32根地址线,每根地址线在寻址的时产生一个电信号(正电/负电,即1或0),那么一共会产生2^32个地址,而每个地址标识一个字节,那就可以给2^32Byte=4GB的空间进行编址。对于64位的机器同理。

问题3:一个指针变量的大小(存储空间)是多少?

答:对于32位的机器,地址由32个0/1组成,那地址就得用4个字节的空间存储,所以此时一个指针变量的大小是4个字节。同理,对于64位的机器,一个指针变量的大小是8个字节。总结:32位平台上一个指针变量是4字节,64位平台上一个指针变量是8字节。

二、指针和指针类型

虽然在同一个平台上,所有类型的指针所占存储空间大小相同,但区分指针类型仍然是有意义的。

1.指针的解引用操作

指针类型决定了指针进行解引用操作时能访问的空间大小

​int* p;​​​,​​*p​​能够访问4个字节

​char* p;​​​,​​*p​​能够访问1个字节

​double* p;​​​,​​*p​​能够访问8个字节

2.指针+-整数

指针类型决定了指针向前/后走一步走多远(指针的步长)

​int* p;​​​,​​p+1​​向后走4个字节

​char* p;​​​,​​p+1​​向后走1个字节

​double* p;​​​,​​p+1​​向后走8个字节

#include <stdio.h>
int main()
{
int a = 0x11223344;
int* pa = &a;
char* pc = &a;

printf("%p\n", pa);
printf("%p\n", pa+1);

printf("%p\n", pc);
printf("%p\n", pc+1);
return 0;
}
//输出结果:
//0095FB58
//0095FB5C
//0095FB58
//0095FB59

三、野指针

野指针就是指向的位置是不可知的(随机的/不正确的/没有明确限制的)指针。

1.野指针成因

(1)指针未初始化

局部变量不初始化,默认是随机值。

int main()
{
int* p;//p是局部的指针变量,不初始化,默认是随机值
*p = 20;
return 0;
}

(2)指针越界访问

指针指向的范围超出数组arr的范围。

int main()
{
int arr[10] = {0};
int* p = arr;
int i = 0;
for(i=0; i<12; i++)
{
p++;//指针指向的范围超出数组arr的范围
}
return 0;
}

(3)指针指向的空间释放

当函数结束时,参量的空间就会被释放。

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

int main()
{
int* p = test();
*p = 20;//当test()函数结束时,空间已经被释放,所以*p指向的是释放的空间
return 0;
}

2.如何规避野指针

(1)指针要初始化

int main()
{
int a = 10;
int* pa = &a;//初始化
int* p = NULL;//初始化,置空NULL
return 0;
}

(2)小心指针越界

(3)指针指向空间释放,及时置空(NULL)

int main()
{
int a = 10;
int* pa = &a;
*pa = 20;
pa = NULL;//不再用a了,置空NULL
return 0;
}

(4)指针使用之前检查有效性

四、指针运算

1.指针+-整数

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

2.指针-指针

指针-指针得到的是两个指针间的元素个数

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

例1:用指针实现strlen函数(求字符串长度)

#include <stdio.h>
my_strlen(char* str)
{
char* start = str;
char* end = str;
while(end != '\0')
{
end++;
}
return end - start;
}

int main()
{
char arr[] = "bit";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}

3.指针的关系运算

关系运算就是比较大小

#define N_VALUES 5
int main()
{
float values[N_VALUES];
float* vp;
for(vp = &values[N_VALUES]; vp > &values[0];)//">"就是指针的比较大小
{
*--vp = 0;
}
}

注意:标准规定,C语言中允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向数组第一个元素之前的那个内存位置的指针进行比较。

五、指针和数组

数组名就是数组首元素的地址,但有两个例外。详见文章【数组】

例外1:sizeof(数组名),此时数组名表示整个数组,sizeof(数组名)计算的是整个数组的大小(单位:字节)。

例外2:&数组名,此时数组名表示整个数组,&数组名取出的是整个数组的地址。

因此,我们可以直接通过指针来访问数组。​​p+i​​​表示的就是数组中下标为​​i​​的元素。

int main()
{
int arr[10] = {0};
int* p = arr;
int i = 0;
for(i=0; i<10; i++)
{
*(p + i) = i;
}
for(i=0; i<10; i++)
{
printf("%d", *(p + i));
}
return 0;
}
//输出结果为0 1 2 3 4 5 6 7 8 9

六、二级指针

指针是一种变量,自然需要地址存放,存放指针的变量就叫二级指针。以此类推,存储n级指针的变量就叫n+1级指针。

int main()
{
int a = 10;
int* pa = &a;
int** ppa = &pa;//ppa就是二级指针
int*** pppa = &ppa;//pppa就是三级指针

printf("%d\n", **ppa);//输出10,即a的值
//**ppa等价于*pa等价于a
return 0;
}

七、指针数组

注意区分指针数组和数组指针:

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

数组指针:是指针。

指针数组示例:

int main()
{
int a = 10;
itn b = 20;
int c = 30;
int* pa = &a;
int* pb = &b;
int* pc = &c;
return 0;
}

可以改写成

int main()
{
int a = 10;
int b = 20;
int c = 30;
int* arr[3] = {&a, &b, &c};

int i = 0;
for(i=0; i<3; i++)
{
printf("%d ", *(arr[i]));
}
return 0;
}
//输出结果:10 20 30

标签:arr,return,int,初识,数组,main,指针
From: https://blog.51cto.com/u_15883132/5992187

相关文章

  • 初识MySQL(三)CRUD操作
    insert增加   update更新updateusersetage=23wherename='zhangsan';updateusersetage=age+1whereid=3; delete删除deletefr......
  • C | 指针
    1.什么是指针指针是一种变量,也称指针变量,它的值不是整数、浮点数和字符,而是内存地址。指针的值就是变量的地址,而变量有拥有一个具体值。因此,可以理解为变量直接引用了一个......
  • C语言指针常见问题
    我们在学C语言时,指针是我们最头疼的问题之一,针对C语言指针,博主根据自己的实际学到的知识以及开发经验,总结了以下使用C语言指针时常见问题。指针指针做函数参数学习......
  • C-指针的本质
    指针:一个变量的地址称为该变量的“指针”。定义一个指针:int*i_pointer;//指针变量名为i_pointer注:sizeof(i_pointer)在64位程序中......
  • go语言之初识gin
    1.首先搭环境1.1安装go1.2创建目录1.3在当前目录下执行 gomodinitxxx_name1.4在当前目录下执行  gomodinitxxx_name1.5最简单的......
  • Unity跳转场景报空指针解决
    当跳转场景时,有时候会出现空指针问题。解决办法:将即将跳转到的scene添加到BuildSettings里面。举个例子:例如从某个场景要跳转到network这个场景中,那么BuildSettings里面必......
  • Go 指针
    funcmain(){ varage=18//申明一个变量age,值为18 varptr*int=&age//*int是指针类型,可以理解为指向int类型的指针;&age是指针的指向的内存地址 prin......
  • FreeSWITCH学习笔记3(3.5)- 初识FreeSWITCH
    目录配置SIP网关拨打外部电话:从某一分机上呼出呼入电话处理 配置SIP网关拨打外部电话 originatesofia/gateway/zlz/1003&echo(前提是设置了1003,并且选定了才......
  • FreeSWITCH学习笔记3(3.3、3.4)- 初识FreeSWITCH
    目录:1、配置FreeSWITCH2、FreeSWITCH用作软电话 1、配置FreeSWITCH具体参考:《FreeSWITCH权威指南》3.3节以下,将通过添加一个新的FreeSWITCH用户来简单熟悉一下Free......
  • FreeSWITCH学习笔记3(3.1、3.2)- 初识FreeSWITCH
    目录:FreeSWITCH的功能连接SIP电话连接SIP电话——实操 1、FreeSWITCH的功能  安装完成FreeSWITCH后,以管理员身份运行。通过在控制台中输入:shutdown......