C语言入门 | 一文理解指针

本文详细介绍了C语言中的指针基础知识,包括内存、地址、指针的概念,指针的使用(定义、初始化和运算),以及多级指针、数组与指针的关系、字符指针、函数指针和void*指针的特性和应用。
摘要由CSDN通过智能技术生成

目录

一.指针基础知识

1.1何为 内存/地址/指针?

1.2指针的使用

1.2.1定义指针变量

1.2.3 两个指针会用到的运算符:&和*

1.3指针变量的大小

1.4指针与整数的运算

二、多级指针

三.数组和指针

3.1. 数组名的理解

3.2使用指针访问数组

3.3指针数组&数组指针

3.3.1指针数组

3.3.2 数组指针

四、字符指针

五、函数指针

5.1 函数指针变量的创建

5.2 函数指针变量的使⽤

5.3函数指针数组

六、void*指针


一.指针基础知识

1.1何为 内存/地址/指针?

内存和地址可以用一个形象的例子理解:

生活中,我们想要去一个陌生小区找一个朋友,朋友会告诉我们他住在几栋几单元几号。我们可以直接通过朋友告诉的门牌编号找到他,非常方便。否则我们只有一间一间的去询问,效率非常的低下。

而在计算机中,内存就是这一个一个的房间,地址就是门牌编号,在C语言中它也有一个新名字“指针”,通过地址(指针)的信息,我们就可以很方便的找到我么们需要寻找的内存,进而得到想要的信息啦!

总结一下,我们可以这样的简单理解:门牌编号==地址==指针

1.2指针的使用

1.2.1定义指针变量

这里举出两个例子:

int* p //整形指针变量,指针类型为int*,指针指向int
char* p //字符指针变量,指针类型为char*,指针指向char

int* p :整形指针变量,指针类型为int*,指针指向int

char* p :字符指针变量,指针类型为char*,指针指向char

总结:指向类型* 变量名

1.2.2初始化指针变量

指针变量在定义时可以赋值,即初始化。可以赋值为“NULL”或“0”。

int *p1= NULL, *p2 = 0;

1.2.3 两个指针会用到的运算符:&和*

取地址运算符&:单目运算符&可以用来取操作对象的地址。

#include <stdio.h>
int main(){
 int a = 10;
 &a;//取出a的地址
 printf("%p\n", &a);
 return 0;
}

代码结果:就可以打印出a的地址啦。
指针运算符*:* 则可以通过地址,获取内存中的内容。(地址是不能直接使用的!)

#include <stdio.h>
int main()
{
 int a = 100;
 int* pa = &a;
 *pa = 0;
 return 0;
}

通过*pa就可以直接对a进行操作,这里把a的值改成了0

1.3指针变量的大小

直接上结论:
32位平台下地址是32个bit位,指针变量⼤⼩是4个字节
64位平台下地址是64个bit位,指针变量⼤⼩是8个字节
注意指针变量的⼤⼩和类型是⽆关的,只要指针类型的变量,在相同的平台下,⼤⼩都是相同的。

1.4指针与整数的运算

指针+ 1 或减-1 运算,表示指针向前或向后移动一个单元(不同类型的指针,单元长度不同)。

eg.char* 类型的指针变量+1跳过1个字节
      int* 类型的指针变量+1跳过了4个字节。
结论:指针的类型决定了指针向前或者向后⾛⼀步有多⼤(距离)。

二、多级指针

指针变量也是变量,是变量就有地址
我们通过二级指针来了解:
#include <stdio.h>
int main()
{
int a=10; 
int*pa=&a;
int ** ppa=&pa;

return 0;
}

ppa:指向指针变量的指针,指针变量pa的地址。

三.数组和指针

3.1. 数组名的理解

这⾥我们使⽤ &arr[0] 的⽅式拿到了数组第⼀个元素的地址,但是其实数组名本来就是地址,⽽且
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("&arr[0] = %p\n", &arr[0]);
printf("arr = %p\n", arr);
return 0;
}
输出结果: 地址打印出的结果⼀模⼀样
结论:数组名就是数组⾸元素(第⼀个元素)的地址。
两个例外:
sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩, 单位是字节
&数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素 的地址是有区别的)
除此之外,任何地⽅使⽤数组名,数组名都表⽰⾸元素的地址。

3.2使用指针访问数组

我们可以使⽤arr[i]可以访问数组的元素,那p[i]是否也可 以访问数组呢?
#include <stdio.h>
int main()
{
int arr[10] = {0};
//输⼊
int i = 0;
int sz = sizeof(arr)/sizeof(arr[0]);
//输⼊
int* p = arr;
for(i=0; i<sz; i++)
{
scanf("%d", p+i);
//scanf("%d", arr+i);//也可以这样写
}
//输出
for(i=0; i<sz; i++)
{
printf("%d ", p[i]);
}
return 0;
}
两种不同写法的输出的结果是一致的。
结论:本质上p[i] 是等价于 *(p+i)。

3.3指针数组&数组指针

3.3.1指针数组

本质是数组,数组中存储的内容是指针变量。

3.3.2 数组指针

本质是指针,指针指向的内容是数组。

int (*p)[10];
解释:p先和*结合,说明p是⼀个指针变量变量,然后指着指向的是⼀个⼤⼩为10个整型的数组。所以 p是⼀个指针,指向⼀个数组,叫 数组指针。
这⾥要注意:[]的优先级要⾼于*号的,所以必须加上()来保证p先和*结合。
数组指针变量初始化
int (*p)[10]=&arr;

四、字符指针

字符指针类型  char* ;
int main()
{
const char* pstr = "hello";//这⾥不是把⼀个字符串放到pstr指针变量⾥,而是字符数组首地址
printf("%s\n", pstr);
return 0;
}
代码 const char* pstr = "hello"; 本质是把字符串” hello“ ⾸字符的地址放到了pstr中。
可以把定义的指针看做是字符数组的数组名,字符串的实质是字符数组。

五、函数指针

5.1 函数指针变量的创建

函数指针变量应该是⽤来存放函数地址的,未来通过地址能够调⽤函数的。
那么函数是否有地址呢?
#include <stdio.h>
void test()
{
printf("hehe\n");
}
int main()
{
printf("test: %p\n", test);
printf("&test: %p\n", &test);
return 0;
}
输出结果如下:
test: 005913 CA
&test: 005913 C
结论:函数是有地址的,函数名就是函数的地址,也可以通过 & 函数名的⽅
式获得函数的地址。
创建函数指针变量例子
void test()
{
printf("hehe\n");
}
void (*pf1)() = &test;
void (*pf2)()= test;
int Add(int x, int y)
{
return x+y;
}
int(*pf3)(int, int) = Add;
int(*pf3)(int x, int y) = &Add;//x和y写上或者省略都是可以的
int( * )(int,int)就是该函数指针的类型。

5.2 函数指针变量的使⽤

#include <stdio.h>
int Add(int x, int y)
{
return x+y;
}
int main()
{
int(*pf3)(int, int) = Add;

printf("%d\n", (*pf3)(2, 3));
printf("%d\n", pf3(3, 5));
return 0;
}
输出结果:
5
8

5.3函数指针数组

把函数的地址存到⼀个数组中,那这个数组就叫函数指针数组
int (*parr1[3])();

该数组的内容就是:int (* )()类型的函数

六、void*指针

  void* 指针是一种特殊类型的指针 ,可以理解为⽆具体类型的指针
特点:这种类型的指针可以⽤来接受任意类型地址。
局限性:  void* 类型的指针不能直接进 ⾏指针的+-整数和解引⽤的运算。
使⽤void*类型的指针接收地址:
#include <stdio.h>
int main()
{
int a = 10;
void* pa = &a;
void* pc = &a;

*pa = 10;
*pc = 0;
return 0;
}
用处⼀般 void* 类型的指针是使⽤在函数参数的部分,⽤来接收不同类型数据的地址,这样的设计可以 实现泛型编程的效果。使得⼀个函数来处理多种类型的数据。
 
  • 30
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值