11深入理解C指针之---指针和常量
该系列文章源于《深入理解C指针》的阅读与理解,由于本人的见识和知识的欠缺可能有误,还望大家批评指教。
指针作为C语言的左膀右臂,使用方便,修改容易,引用数据快速都是很有前景的应用。C语言中常量是值不能改变的量,由于在某些应用中,想要阻止没有授权的数据的修改时,就需要将指针和常量结合起来。
先看以下代码:
1 #include <stdio.h> 2 3 int main(int argc, char **argv) 4 { 5 int iVar1 = 30; 6 int *ptrVar1 = &iVar1; 7 printf("iVar1 value: %d and iVar1 address: %#x\n", iVar1, &iVar1); 8 printf("*ptrVar1 value: %d ptrVar1 value: %#x and ptrVar1 address: %#x\n", *ptrVar1, ptrVar1, &ptrVar1); 9 10 iVar1++; 11 printf("iVar1 value: %d and iVar1 address: %#x\n", iVar1, &iVar1); 12 printf("*ptrVar1 value: %d ptrVar1 value: %#x and ptrVar1 address: %#x\n", *ptrVar1, ptrVar1, &ptrVar1); 13 14 (*ptrVar1)++; 15 printf("iVar1 value: %d and iVar1 address: %#x\n", iVar1, &iVar1); 16 printf("*ptrVar1 value: %d ptrVar1 value: %#x and ptrVar1 address: %#x\n", *ptrVar1, ptrVar1, &ptrVar1); 17 18 return 0; 19 }
代码结果:
iVar1 value: 30 and iVar1 address: 0x5b483c1c *ptrVar1 value: 30 ptrVar1 value: 0x5b483c1c and ptrVar1 address: 0x5b483c10 iVar1 value: 31 and iVar1 address: 0x5b483c1c *ptrVar1 value: 31 ptrVar1 value: 0x5b483c1c and ptrVar1 address: 0x5b483c10 iVar1 value: 32 and iVar1 address: 0x5b483c1c *ptrVar1 value: 32 ptrVar1 value: 0x5b483c1c and ptrVar1 address: 0x5b483c10
通过以上代码不难发现,将指针指向变量后,无论通过指针或变量都可以轻松修改变量。有时只是想利用指针的便利,而又不想承担指针可以修改变量的风险是,与const结合无疑是最好的。
一、const修饰指针定义:通过指针引用的方式修改变量将会被禁止
1、特征:
1)、提供一种特殊的方式来操纵数据
2)、指针的值可以改变
3)、不能通过指针改变指向变量的值
2、两种形式,两种形式完全一样的:
1)、int const *ptrVar1;
2)、const int *ptrVar1;
将代码1的第6行代码改为如下:
6 int const *ptrVar1 = &iVar1;
代码编译错误如下:
test11_01.c:14:12: 错误:令只读位置‘*ptrVar1’自增 (*ptrVar1)++; ^~
只有将第14行如下代码注释掉,才能通过编译:
(*ptrVar1)++;
再看如下代码段:
1 #include <stdio.h> 2 3 int main(int argc, char **argv) 4 { 5 int iVar1 = 30; 6 int iVar2 = 90; 7 int const *ptrVar1 = &iVar1; 8 printf("iVar1 value: %d and iVar1 address: %#x\n", iVar1, &iVar1); 9 printf("*ptrVar1 value: %d ptrVar1 value: %#x and ptrVar1 address: %#x\n", *ptrVar1, ptrVar1, &ptrVar1); 10 11 iVar1++; 12 printf("iVar1 value: %d and iVar1 address: %#x\n", iVar1, &iVar1); 13 printf("*ptrVar1 value: %d ptrVar1 value: %#x and ptrVar1 address: %#x\n", *ptrVar1, ptrVar1, &ptrVar1); 14 15 ptrVar1 = &iVar2; 16 printf("iVar2 value: %d and iVar2 address: %#x\n", iVar2, &iVar2); 17 printf("*ptrVar1 value: %d ptrVar1 value: %#x and ptrVar1 address: %#x\n", *ptrVar1, ptrVar1, &ptrVar1); 18 19 return 0; 20 }
结果如下:
iVar1 value: 30 and iVar1 address: 0xf15c983c *ptrVar1 value: 30 ptrVar1 value: 0xf15c983c and ptrVar1 address: 0xf15c9830 iVar1 value: 31 and iVar1 address: 0xf15c983c *ptrVar1 value: 31 ptrVar1 value: 0xf15c983c and ptrVar1 address: 0xf15c9830 iVar2 value: 90 and iVar2 address: 0xf15c9838 *ptrVar1 value: 90 ptrVar1 value: 0xf15c9838 and ptrVar1 address: 0xf15c9830
根据定义,容易知道由于const修饰的是*ptrVar1,是指针的引用,因此无法通过指针引用修改变量的值,但是依旧可以通过变量赋值修改变量,而且指针变量可以指向其他变量如iVar2等。
二、const修饰指针定义:可以通过指针引用的方式修改变量,禁止指针指向其他变量
1、特征:
1)、提供一种特殊的方式来操纵数据
2)、指针的值不可以改变
3)、通过指针改变指向变量的值
2、应用形式:
1)、int * const ptrVar1;
将代码2的第6行代码改为如下:
6 int * const ptrVar1 = &iVar1;
代码编译错误如下:
test11_01.c:15:10: 错误:向只读变量‘ptrVar1’赋值
ptrVar1 = &iVar2;
只有将第15行如下代码注释掉或改为(*ptrVar1)++,才能通过编译:
ptrVar1 = &iVar2;
请看如下具体代码段:
1 #include <stdio.h> 2 3 int main(int argc, char **argv) 4 { 5 int iVar1 = 30; 6 int *const ptrVar1 = &iVar1; 7 printf("iVar1 value: %d and iVar1 address: %#x\n", iVar1, &iVar1); 8 printf("*ptrVar1 value: %d ptrVar1 value: %#x and ptrVar1 address: %#x\n", *ptrVar1, ptrVar1, &ptrVar1); 9 10 iVar1++; 11 printf("iVar1 value: %d and iVar1 address: %#x\n", iVar1, &iVar1); 12 printf("*ptrVar1 value: %d ptrVar1 value: %#x and ptrVar1 address: %#x\n", *ptrVar1, ptrVar1, &ptrVar1); 13 14 //ptrVar1 = &iVar2; 15 (*ptrVar1)++; 16 printf("iVar1 value: %d and iVar1 address: %#x\n", iVar1, &iVar1); 17 printf("*ptrVar1 value: %d ptrVar1 value: %#x and ptrVar1 address: %#x\n", *ptrVar1, ptrVar1, &ptrVar1); 18 19 return 0; 20 }
根据定义,容易知道由于const修饰的是ptrVar1,是指针变量自身,指针的值不能改变。因此可以通过指针引用修改变量的值,也可以通过变量赋值修改变量,但是指针变量不可以指向其他变量如iVar2等。
三、const修饰指针定义,同时修改指针变量:通过指针引用的方式修改变量将会被禁止,指针也不能指向其他变量
1、特征:
1)、提供一种特殊的方式来操纵数据
2)、指针的值不可以改变
3)、不可通过指针改变指向变量的值
2、应用形式:
1)、int const * const ptrVar1;
代码如下:
1 #include <stdio.h> 2 3 int main(int argc, char **argv) 4 { 5 int iVar1 = 30; 6 int iVar2 = 90; 7 int const *const ptrVar1 = &iVar1; 8 printf("iVar1 value: %d and iVar1 address: %#x\n", iVar1, &iVar1); 9 printf("*ptrVar1 value: %d ptrVar1 value: %#x and ptrVar1 address: %#x\n", *ptrVar1, ptrVar1, &ptrVar1); 10 11 iVar1++; 12 printf("iVar1 value: %d and iVar1 address: %#x\n", iVar1, &iVar1); 13 printf("*ptrVar1 value: %d ptrVar1 value: %#x and ptrVar1 address: %#x\n", *ptrVar1, ptrVar1, &ptrVar1); 14 >>15 ptrVar1 = &iVar2; 16 //(*ptrVar1)++; 17 printf("iVar1 value: %d and iVar1 address: %#x\n", iVar1, &iVar1); 18 printf("*ptrVar1 value: %d ptrVar1 value: %#x and ptrVar1 address: %#x\n", *ptrVar1, ptrVar1, &ptrVar1); 19 20 return 0; 21 }
保留第15行代码,编译错误如下:
test11_01.c:15:10: 错误:向只读变量‘ptrVar1’赋值 ptrVar1 = &iVar2; ^
保留第16行代码,编译错误如下:
test11_01.c:16:12: 错误:令只读位置‘*ptrVar1’自增 (*ptrVar1)++; ^~
由此可见,通过两个const的修饰,使得无论是指针变量的值,还是指针变量的解引用值都无法改变,可以有效提高数据的安全性。