C语言const int *a和int*const a 的区别详解
对于“const int*p”与“int*const p”这两种声明方式,相信很多程序员都会头痛。它们两者之间究竟有什么不同之处呢?为了加深大家对这两种声明方式的理解,下面就先从“const int i”与“int const i”之间的区别谈起。
对于 const 关键字,相信大家并不陌生,前面的章节也做了相关的说明。对变量来说,const 关键字可以限定一个变量的值不允许改变,从而保护被修饰的东西,防止意外修改,在一定程度上可以提高程序的安全性和可靠性。如下面的示例代码所示:
理解“const int i”与“int const i”之后,继续来看“const int*p”与“int*const p”这两种声明方式,看下面的例子:
其实回答上面的问题并不难,只要注意如下两点:
首先,这里的 const 关键字修饰的是整个“*p”,而不是 p。所以这里的“*p”是不能被赋值的,也就是说我们不能通过“*p”来修改 i2 的值。
其次,p 前并没有用 const 关键字进行修饰,所以 p 是指针变量,能被赋值重新指向另一内存地址。也就是说下面的代码是合法的:
这个时候,我们就要使用“int*const p”这种声明形式了。很显然,这里的 const 是写在 p 前和 * 号后的,而不是写在“*p”前的,所以它是用来修饰限定 p 的。如下面的示例代码所示:
在了解“const int*p”与“int*const p”两者之间的区别之后,为了巩固大家的理解,继续看下面的示例:
示例运行结果为:
*p=10
i=10
*p=20
对于 const 关键字,相信大家并不陌生,前面的章节也做了相关的说明。对变量来说,const 关键字可以限定一个变量的值不允许改变,从而保护被修饰的东西,防止意外修改,在一定程度上可以提高程序的安全性和可靠性。如下面的示例代码所示:
const int i=10; i++;很显然,上面的语句“i++”是错误的,无法通过编译,因为 const 修饰的变量 i 是不可以被修改的。然而对于下面的语句:
int const i=10; i++;对于语句“i++”,编译器会报同样的错误提示。由此可见,“const int i”与“int const i”是完全相同的概念,const 与 int 哪个写在前面都不影响语义,理解这一点很重要。
理解“const int i”与“int const i”之后,继续来看“const int*p”与“int*const p”这两种声明方式,看下面的例子:
int i1 = 10; int i2 = 20; const int *p = &i1; /* 输出结果是10 */ printf("%d\n", *p); p = &i2; /* 输出结果是20 */ printf("%d\n", *p); i2 = 30; /* 输出结果是30 */ printf("%d\n", *p);或许这个时候看了上面的示例代码,你会有这样一个疑问:为什么 p 的值是可以被修改的,它可以重新指向另一个地址呢?
其实回答上面的问题并不难,只要注意如下两点:
首先,这里的 const 关键字修饰的是整个“*p”,而不是 p。所以这里的“*p”是不能被赋值的,也就是说我们不能通过“*p”来修改 i2 的值。
其次,p 前并没有用 const 关键字进行修饰,所以 p 是指针变量,能被赋值重新指向另一内存地址。也就是说下面的代码是合法的:
p = &i2; i2 = 30;看到这里,你也许会更加疑惑:那又该如何使用 const 来修饰 p 呢?
这个时候,我们就要使用“int*const p”这种声明形式了。很显然,这里的 const 是写在 p 前和 * 号后的,而不是写在“*p”前的,所以它是用来修饰限定 p 的。如下面的示例代码所示:
int i1 = 10; int i2 = 20; int *const p = &i1; /* 输出结果是10 */ printf("%d\n", *p); /* p=&i2; p不能再这样重新赋值了,即不能再指向另一个新地址*/ /* 可以通过*p修改i1的值*/ i1 = 30; /* 输出结果是30 */ printf("%d\n", *p);从上面的示例代码可以看出,通过“int*const p”声明之后,p 因为有了 const 的修饰,所以只是一个指针常量。因此,这里的 p 值是不能重新赋值修改的,它只能永远指向初始化时的内存地址。即下面的代码是不合法的:
p = &i2; /*p不能再这样重新赋值了,即不能再指向另一个新地址*/但是,也正因为这里的整个“*p”的前面没有 const 修饰。也就是说,“*p”是变量而不是常量,所以我们可以通过“*p”来修改它所指内存 i1 的值。因此,下面的语句是合法的:
i1 = 30;由此可见,如果关键字 const 直接写在“*p”前,则程序不能修改“*p”,但可以修改 p;如果关键字 const 直接写在 p 前,则程序不能修改的是 p,但可以通过“*p”来修改它所指内存的值。理解这两点很重要,否则很难掌握“const int*p”与“int*const p”两者之间的根本区别。
在了解“const int*p”与“int*const p”两者之间的区别之后,为了巩固大家的理解,继续看下面的示例:
const int i=10; int *p; /* 强制类型转换*/ p= (int *) &i; printf("*p=%d\n",*p) /*这种赋值是合法的*/ *p=20; printf("i=%d\n",i); printf("*P=%d\n",*p);在上面的代码中,因为 const int 类型的 i 的地址是不能赋值给指向 int 类型地址的指针 p 的(否则 p 岂不是能修改i的值)。因此下面的语句是不合法的:
p = &i;但是,可以通过强制类型转换进行赋值,因此下面的这种赋值方法是合法的:
p= (int *) &i; *p=20;但值得注意的是,尽管可以通过强制类型转换进行赋值,也不能通过“*p=20”来修改 i 的值。因此,“printf("i=%d\n”,i)”输出的结果是 10,并不是 20。
示例运行结果为:
*p=10
i=10
*p=20
所有教程
- C语言入门
- C语言编译器
- C语言项目案例
- 数据结构
- C++
- STL
- C++11
- socket
- GCC
- GDB
- Makefile
- OpenCV
- Qt教程
- Unity 3D
- UE4
- 游戏引擎
- Python
- Python并发编程
- TensorFlow
- Django
- NumPy
- Linux
- Shell
- Java教程
- 设计模式
- Java Swing
- Servlet
- JSP教程
- Struts2
- Maven
- Spring
- Spring MVC
- Spring Boot
- Spring Cloud
- Hibernate
- Mybatis
- MySQL教程
- MySQL函数
- NoSQL
- Redis
- MongoDB
- HBase
- Go语言
- C#
- MATLAB
- JavaScript
- Bootstrap
- HTML
- CSS教程
- PHP
- 汇编语言
- TCP/IP
- vi命令
- Android教程
- 区块链
- Docker
- 大数据
- 云计算