C语言 const使用详解

Posted 流楚丶格念

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言 const使用详解相关的知识,希望对你有一定的参考价值。

const前导知识

定义

它是定义只读变量的关键字,或者说 const 是定义常变量的关键字。

const 定义的是变量,但又相当于常量;说它定义的是常量,但又有变量的属性,所以叫常变量

基本用法

用 const 定义的变量的值是不允许改变的,即不允许给它重新赋值,即使是赋相同的值也不可以。所以说它定义的是只读变量。这也就意味着必须在定义的时候就给它赋初值。

修饰变量

用 const 修饰的变量,无论是全局变量还是局部变量,生存周期都是程序运行的整个过程。全局变量的生存周期为程序运行的整个过程这个是理所当然的。而使用 const 修饰过的局部变量就有了静态特性,它的生存周期也是程序运行的整个过程。我们知道全局变量是静态的,静态的生存周期就是程序运行的整个过程。但是用const修饰过的局部变量只是有了静态特性,并没有说它变成了静态变量。

补充一下:局部变量存储在栈中,静态变量存储在静态存储区中,而经过 const 修饰过的变量存储在内存中的“只读数据段”中。只读数据段中存放着常量和只读变量等不可修改的量。)

变量?常量?

前面说过 const 是定义只读变量的关键字,所以归根结底这个定义的只读变量最后也是变量,但是我们用的时候就相当于是定义一个常量

const定义的是变量,而define定义的是常量。

const与define的区分:

这一点他和 define是有区分的:

  • define是预编译指令,而const是普通变量的定义。define定义的宏是在预处理阶段展开的,而const定义的只读变量是在编译运行阶段使用的。
  • define定义的宏在编译后就不存在了,它不占用内存,因为它不是变量,系统只会给变量分配内存。但const定义的常变量本质上仍然是一个变量,具有变量的基本属性,有类型、占用存储单元。
  • const定义的是变量,而宏定义的是常量,所以const定义的对象有数据类型,而宏定义的对象没有数据类型。

代码应用

const 定义变量

定义

const int i = 0;
//i = 100; //如果下面加这句的话为 错误,只读变量初始化之后不能修改

并且定义const变量最好初始化,下面的代码在vs中就会报错。

const int j;	// 报错

修改const 变量值

c语言的const是一个只读变量,并不是一个常量,可通过指针间接修改。

参考下面的代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void test01() {

	// c语言的const是一个只读变量,并不是一个常量,可通过指针间接修改
	const int k = 10;
	//k = 100; //错误,不可直接修改,我们可通过指针间接修改
	printf("k:%d\\n", k);
	int* p = (int *)(&k);
	*p = 100;
	printf("k:%d\\n", k);
}

int main()
{
	test01();
	return 0;
}

更详细的探究可以参考这篇博文,我没有在g++里面试,我在VS里试不能改
https://blog.csdn.net/heyabo/article/details/8745942

const 修饰指针

const放在*号左侧,修饰指针指向的内存空间不能修改,但可修改指针的指向,这里相当于修饰 普通数据变量,不可以修改变量的存的值。

const放在*号的右侧,修饰指针的指向不能修改,但是可修改指针指向的内存空间,这里相当于修饰的指针变量,不可以修改指针的值,但可以修改存的值。

const放在*号的左右两侧,那么就是说明指针的指向和指针指向的内存空间都不能修改,也就是存的数据值和指针的指向都不能改。

看下面的代码理解一下:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void test() {

	int a = 10;
	int b = 20;
	//const放在*号左侧 修饰p_a指针指向的内存空间不能修改,但可修改指针的指向
	const int* p_a = &a;
	printf("修改前 *p_a:%d\\n",*p_a);
	//*p_a = 100; //不可修改指针指向的内存空间
	p_a = &b; //可修改指针的指向
	printf("修改后 *p_a:%d\\n", *p_a);

	printf("-------------------\\n", *p_a);
	//const放在*号的右侧, 修饰指针的指向不能修改,但是可修改指针指向的内存空间
	int* const p_b = &a;
	printf("修改前 *p_b:%d\\n", *p_b);
	//p_b = &b; //不可修改指针的指向
	*p_b = 100; //可修改指针指向的内存空间
	printf("修改后 *p_b:%d\\n", *p_b);

	//指针的指向和指针指向的内存空间都不能修改
	const int* const p_c = &a;
}
int main()
{
	test();

	return 0;
}

const 与 struct 的爱恨情仇

例如下面的结构体,

struct Person {
	char name[64];
	int id;
	int age;
	int score;
};

如果我想打印结构体变量的信息,普通的写法就是这样写

// 每次都对对象进行拷贝,效率低,应该用指针
void printPersonByValue(struct Person person) {
	printf("Name:%s\\n", person.name);
	printf("Name:%d\\n", person.id);
	printf("Name:%d\\n", person.age);
	printf("Name:%d\\n", person.score);
}

但是这样,每次传入的是形式参数,形式参数每次都对 对象进行拷贝,效率低,那么我们应该要用指针

// 但是用指针会有副作用,可能会不小心修改原数据
void printPersonByPointer(struct Person *person) {
	printf("Name:%s\\n", person->name);
	printf("Name:%d\\n", person->id);
	printf("Name:%d\\n", person->age);
	printf("Name:%d\\n", person->score);
}

但是直接用指针会有副作用,可能会不小心修改原数据,如果我在打印函数里去使用结构体变量的话,那么就可能会对原来的数据造成破坏。

这里我们就要用到const,来修饰传入的参数,作为只读实际参数,不让用户对其进行修改

// 解决
void printPersonByPointer(const struct Person *person) {
	printf("Name:%s\\n", person->name);
	printf("Name:%d\\n", person->id);
	printf("Name:%d\\n", person->age);
	printf("Name:%d\\n", person->score);
}

全部代码我也放在这

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//const指针用法
struct Person {
	char name[64];
	int id;
	int age;
	int score;
};

//每次都对对象进行拷贝,效率低,应该用指针
void printPersonByValue(struct Person person) {
	printf("Name:%s\\n", person.name);
	printf("Name:%d\\n", person.id);
	printf("Name:%d\\n", person.age);
	printf("Name:%d\\n", person.score);
}


//但是用指针会有副作用,可能会不小心修改原数据
void printPersonByPointe(struct Person *person) {
	printf("Name:%s\\n", person->name);
	printf("Name:%d\\n", person->id);
	printf("Name:%d\\n", person->age);
	printf("Name:%d\\n", person->score);
}

//但是用指针会有副作用,可能会不小心修改原数据
void printPersonByPointer(const struct Person *person) {
	printf("Name:%s\\n", person->name);
	printf("Name:%d\\n", person->id);
	printf("Name:%d\\n", person->age);
	printf("Name:%d\\n", person->score);
}
void test() {
	struct Person p = { "Obama", 1101, 23, 87 };
	//printPersonByValue(p);
	printPersonByPointe(&p);
	printPersonByPointer(&p);
}

int main()
{
	test();

	return 0;
}

以上是关于C语言 const使用详解的主要内容,如果未能解决你的问题,请参考以下文章

C#中const用法详解

c语言中const、static关键字的用法?

C/C++中const关键字详解

请问C语言如何把2个const char * const s1的字符串合并?

基于STM32详解C语言内存分配

C++语言const_iterator和const iterator的区别,