IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> C语言 const使用详解 -> 正文阅读

[JavaScript知识库]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;
}
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-20 12:24:14  更:2021-10-20 12:24:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/13 7:27:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码