理解C指针:(一)指针初探

指针是C语言的精华所在,可以说,学习C语言的指针就是学习C语言管理内存的方式。

 

什么是指针

通俗地讲,指针就是一个储存内存地址的整形变量

 

指针的定义

定义指针跟定义普通变量差不多:

 

int *p; //声明一个指向int型数据的指针

 

格式为 类型* 指针名;

在声明时用int型变量为它赋值:

 

int i = 0;
int *p = &i;

 

需要注意的是,用于给指针赋值的只能是一个确定的内存地址:

 

int *p = 5; //错误,只能用一个确定的地址给指针赋值,5并不占有一块内存地址

如果在声明时不知道指针应该指向哪里,应该用NULL为指针赋值,防止出现一些奇怪的错误 :

 

int *p = NULL;

 

 

 

取地址符"&"

C语言提供了取地址符“&”来获取某程序实体(变量,指针,结构体,甚至是函数等)在内存中的地址,既然是在内存中的地址,那么同样对于没有确定地址的数字常量取地址是错误的。但是对于字符串,函数(在C语言中函数也被解析为是指针),取地址是正确的:

 

int i = &10;//错误
int j = &"abcdef";//合法语句

为什么 &"abcdf" 会是合法的语句呢?因为在C语言中,字符串被认为是字符串在内存中的首地址的指针,对指针取地址当然是合法的

类似下面这样的语句也是合法的:

 

char c[] = "abcd";
printf("%p\n",&c); //用16进制输出

 

使用“*”访问指针指向的内容

 

C语言提供了取值符号“*”来访问指针指向的内容,例如:

 

int i = 5;
int* p = &i;
printf("%d",*p); //等价于 printf("%d",i);

上面这个代码片段运行后会输出数字“5”

同样地,也可以用指针操作目标变量:

 

int i = 5;
printf("%d\n",i); //输出i
int* p = &i;
(*p)++;
printf("%d\n",i); //再次输出i

 

运行上面的代码,会输出数字“5”然后输出数字"6"

 

 

要注意的是,当运算符“*”与++, --运算符同时使用时要特别注意优先级问题,养成多用括号的习惯能避免产生很多奇怪的bug。

那么指针声明语句里的"*"又是代表什么意思呢?实际上在声明语句里,"*"只作为一个标志符,用来说明某个变量是指针变量。

 

指针变量指向的类型

指针的本质是一个int整形变量,但是指针指向的对象有类型之分,因为不同的类型占用不同的内存空间,类型不匹配就会出错,如上文所说的,用一个int型变量给一个int指针赋值:

 

int i = 0;
int *p = &i;

如果用其他类型的变量给int型指针赋值就是错误的:

 

 

long l = 123456789;
int *p = &l; //错误

为什么说这样是错误的呢?

 

在32位的机器上,int类型占4个字节,而long类型占8个字节。声明一个int型指针,指针指向4个字节的数据,将long赋值给int型的指针后,指针指向的内存变成了8个字节,但是指针能读取的大小只有4字节,还有4个字节没办法读取,于是就会造成程序读取到一些很奇怪的数据。如果用低精度的变量给指向高精度(占字节多的)数据类型的指针赋值,就会导致指针额外地改写内存,如果被改写的内存很重要,那么程序就会出错。

 

void类型指针

空类型指针又成为泛指针或者通用指针,空类型指针是C语言关于纯粹地址的一种约定:

 

int i = 5;
int* p = &i;
void* v = p;

 

对于指针p,它指向的是int型数据,而void指针可以指向任意类型,并且任意类型的指针赋值给它都不需要类型转换,反之亦然(实际上有些编译器会提示你要强制类型转换)

 

sizeof操作符

sizeof是C/C++中的一个操作符,简单地说,它的作用就是返回一个对象或者类型所占的内存字节数,例如我们可以用它获得我们机器上int类型所占的大小:

 

printf("%d",sizeof(int));

 

在博主的机器上上面这行代码输出数字“4”,即int占4个字节。还可以看看指针类型占的字节数:

 

printf("%d\n",sizeof(int*));
printf("%d\n",sizeof(char*));
printf("%d\n",sizeof(void*));

 

运行上面的语句,会输出三个同样的数字,例如在博主的机器上输出了三个数字“8”,我的是64位机器,32位机器会输出三个数字“4”,由此也说明不管何种类型的指针,其大小都是一样的,不同的是其指向空间的大小。

此外要注意的是,sizeof()语句会在编译期间被替换成一个常数,所以不能用if去判断类型所占的大小然后编写相应处理代码。

 

 

本节内容就到这里。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值