C语言字面量和常量
目录
引言
1. 字面量
1.1 字符字面量
1.2 整型字面量
1.3 浮点字面量
2. 常量
2.1 使用预处理器指令 #define 定义常量
2.1.1 语法格式
2.1.2 使用举例
2.2 使用 const 关键字定义常量
2.3 使用 #define 和 const 定义常量的区别
引言
看了一些博文,有的文章对字面量和常量区别的不是很明显,个人观点以下对字面量和常量的定义是比较准确的。
字面量是直接在代码中使用的程序运行期间不会改变的没有名字的固定值。所以我们只能用字面量来称呼它,故叫字面量。
常量是用预处理器指令 #define 或 const 关键字定义的在程序运行期间不会改变的在代码中有名字的固定值。
1. 字面量
int i = 100;
像上面语句中的数字 100,这种在程序中不能修改的无法用名字称呼它的字面值常量,叫做字面量。比如 printf("Hello World\n"); 中的 "Hello World\n" 也是字面量。
1.1 字符字面量
在 ASCII 码表中,编码 [0, 31] 和 127 是控制字符,共 33 个字符是不可以打印的,其中编码 [0, 31] 这 32 个字符主要用于控制打印机等外围设备。
编码 [32, 126] 是可显示字符,也就是可以打印在屏幕上。记得以下几个编码规则,在 C语言对字符进行操作的时候,或许挺管用。
- 大写字母 A ~ Z 的 ASCII码 65 ~ 90
- 小写字母 a ~ z 的 ASCII码 97 ~ 122
- 大写字母比小写字母的 ASCII码小 32 (0b00100000,0x20) ,比如: char c = 'a',小写字母变大写字母,c = c - 32 得到,也可以做位与操作,c = c & 0b11011111 得到
- 数字字符 0 ~ 9 的 ASCII码 48 ~ 57,所以一个数字要转换成数字字符,只要将数字 加上 48 (0x30) 即可
- 字符串的终止符为 '\0',ASCII 码为 0
- 换行符 '\n' 的 ASCII码为 10 (0x0A)
对于这些字符字面量,有4种书写格式
1) 用一对单引号把字符括起来(推荐使用)
#include <stdio.h>int main() {char c1 = 'A';printf("%c\n", c1); // Areturn 0;
}
对于不可打印字符和特殊字符,用转义字符书写。
| \n | 换行符 | \t | 水平制表符 |
| \v | 纵向制表符 | \b | 退格符 |
| \r | 回车符 | \f | 换页符 |
| \a | 报警响铃符 | \\ | 反斜杠 |
| \" | 双引号 | \' | 单引号 |
#include <stdio.h>int main() {char c1 = '\\';printf("%c\n", c1);return 0;
}

2) 用编码数值书写
#include <stdio.h>int main() {char c1 = 65; // 十进制,大写字母 A 的ASCII码:65char c2 = 0101; // 八进制char c3 = 0x41; // 十六进制printf("%c,%c,%c\n", c1, c2, c3); // A,A,Areturn 0;
}
3) 对于任何字符,还可以用通用的转义字符书写
- \ooo,其中 ooo 表示三个八进制数字,注意是三个八进制数字,比如即使是编码为 1 的字符,也不能省掉前面那两个0。
- \xhh,其中 x 表示十六进制,hh 是二个十六进制数字
#include <stdio.h>int main() {char c1 = '\x41'; // 十六进制char c2 = '\101'; // 是3位八进制数字,即使编码为 1 的字符,也要写成 '\001',不能写成 '\1'printf("%c,%c", c1, c2); // A,Areturn 0;
}
1.2 整型字面量
整型字面量可以用十进制、八进制、十六进制或二进制来表示。
- 以 0x 或 0X 开头表示十六进制
- 以数字 0 开头表示八进制
- 以 0b 开头表示二进制
- 不带前缀默认是十进制
以下表示同一个整型字面量
15 // 十进制
017 // 八进制
0xf // 十六进制
0b00001111 // 二进制
#include <stdio.h>int main() {int i1 = 15;int i2 = 017;int i3 = 0xf;int i4 = 0b00001111;printf("%d, %d, %d, %d\n", i1, i2, i3, i4);return 0;
}

整型字面量还可以带一个由 U 和 L 组合的后缀,U 和 L 不分先后顺序,U 可以大写也可以小写 u,是 unsigned 的意思,L 可以大写也可以小写 l,是 long 的意思。
15u // 无符号整型字面量
15L // 长整形字面量,推荐用大写 L,因为小写字面 l 和数字 1 很容易混淆
15ul // 无符号长整形字面量
0xfu // 无符号整型字面量
0xfL // 长整形字面量
0xful // 无符号长整型字面量
017u // 无符号整型字面量
017L // 长整形字面量
017ul // 无符号长整型字面量
// limits.h 文件中,int, unsigned int, long, unsigned int 取值范围定义
#define INT_MIN (-2147483647 - 1)
#define INT_MAX 2147483647
#define UINT_MAX 0xffffffff
#define LONG_MIN (-2147483647L - 1)
#define LONG_MAX 2147483647L
#define ULONG_MAX 0xffffffffUL
#include <stdio.h>
#include <limits.h>int main() {unsigned int uiVar = 15u;long longVar = 15L;unsigned long ulVar = 15ul;printf("%u\n", uiVar); // %u 无符号整型格式化输出printf("%d\n", longVar); // %d 以十进制格式化输出有符号整数(在 limits.h 中有定义: long 和 int 的取值范围是一样的)printf("%lu\n", ulVar); // %lu 以无符号长整型格式化输出uiVar = 0xfu;longVar = 0xfL;ulVar = 0xful;printf("%u\n", uiVar); // %u 无符号整型格式化输出printf("%d\n", longVar); // %d 以十进制格式化输出有符号整数(在 limits.h 中有定义: long 和 int 的取值范围是一样的)printf("%lu\n", ulVar); // %lu 以无符号长整型格式化输出uiVar = 017u;longVar = 017L;ulVar = 017ul;printf("%u\n", uiVar); // %u 无符号整型格式化输出printf("%d\n", longVar); // %d 以十进制格式化输出有符号整数(在 limits.h 中有定义: long 和 int 的取值范围是一样的)printf("%lu\n", ulVar); // %lu 以无符号长整型格式化输出return 0;
}

注意:
018 是不对的整型字面量,因为八进制没有数码 8
15uu 是不对的整型字面量,后缀 u 不能重复
15Lu 是正确的整型字面量,跟 15uL表达的是同一个字面量,u和l组合时,不分先后顺序
1.3 浮点字面量
通常用十进制或科学计数法来表示浮点字面量。
- 默认浮点字面量为 double 类型,比如:3.14
- 在数值后面加上后缀 f 或 F 表示 float 类型,比如:3.14f 或 3.14F
- 0 的 double 类型表示为 0. ;0 的 float 类型表示为 0.f 或 0.F
- 对于只有小数部分的浮点字面量,整数部分的 0 可以省略掉不写,比如:.01 等价于 0.01;.01f 等价于 0.01f
- 使用科学计数法时,指数用 e 或 E 表示。比如:3.14e0 或 3.14E0 表示的是 double 类型 3.14;而 3.14e0f 或 3.14E0F 表示的是 float 类型 3.14f
- double 类型 0 用科学计数法表示为 0e0,float 类型 0 用科学计数法表示为 0e0f
#include <stdio.h>int main() {printf("%d, %d\n", sizeof(.01), sizeof(0.01)); // 8, 8printf("%d, %d\n", sizeof(.01f), sizeof(0.01f)); // 4, 4printf("%.2f, %.2f\n", .01, 0.01); // 0.01, 0.01printf("%d, %d\n", sizeof(0.), sizeof(0.f)); // 8, 4printf("%d\n", sizeof(3.14)); // 8printf("%d, %d\n", sizeof(3.14f), sizeof(3.14F)); // 4, 4printf("%d, %d\n", sizeof(3.14e0), sizeof(3.14E0)); // 8, 8printf("%d, %d\n", sizeof(3.14e0f), sizeof(3.14E0F)); // 4, 4printf("%d, %d\n", sizeof(0e0), sizeof(0e0f)); // 8, 4return 0;
}

1.4 字符串字面量
字符串字面量用一对双引号把所有的字符括在里面,比如:"Hello World\n"
- 字符串字面量在内存中编译器会自动在末尾加上一个字符串终止符('\0'),所以字符串在内存中占用的字节数会比字符串的长度多1字节。
- 两个相邻的仅由空格、制表符('\t') 或 换行符('\n') 分开的字符串字面量,可以连接成一个新的字符串字面量。
- 一个字符串过长,在一行放不下时,可以使用反斜杠 ('\') 进行换行。
- 空字符串 "" 在内存在占一个字节,这个字节存的是字符串终止符('\0')。
#include <stdio.h>int main() {printf("Hello World\n"); printf("Hello" " world\n"); // 两个字符串字面量连接成一个新的字符串 "Hello World\n"printf("Hello \
World\n"); // 用 '\' 换行printf("%d\n", sizeof("")); // 1return 0;
}

2. 常量
常量是用预处理器指令 #define 或 const 关键字定义的在程序运行期间不会改变的在代码中有名字的固定值。
2.1 使用预处理器指令 #define 定义常量
2.1.1 语法格式
#define 常量名 常量值
// 以下代码定义了一个名为 PI 的常量
#define PI 3.14
2.1.2 使用举例
#include <stdio.h>#define PI 3.14// 圆周长
double circumference(const double r) {return 2 * PI * r; // 使用了预处理器指令 #define 定义的常量 PI
}int main() {printf("半径为 %.2f 的圆周长 = %.2f\n", 2.0, circumference(2.0));return 0;
}
2.2 使用 const 关键字定义常量
2.2.1 语法格式
const 常量类型 常量名 = 常量值;
// 以下代码定义了一个名为 PI 的常量
const double PI = 3.14;
2.2.2 使用举例
#include <stdio.h>const double PI = 3.14;// 圆周长
double circumference(const double r) {return 2 * PI * r; // 使用了用 const 关键字定义的常量 PI
}int main() {printf("半径为 %.2f 的圆周长 = %.2f\n", 2.0, circumference(2.0));return 0;
}
注意:用 const 关键字定义的常量,必须同时它进行初始化
/*
// 以下对定义常量 MAX 是错误的,因为常量必须在定义的时同时对它进行初始化,初始化后的常量是不能改变的
const int MAX;
MAX = 100;
*/
// 正确用 const 定义 MAX 常量的方法
const int MAX = 100;
2.3 使用 #define 和 const 定义常量的区别
- 1. 编译器处理方式不同
- 使用 #define 定义的常量会在预处理阶段用它对应的字面量替换掉代码中的常量字符标识,在程序运行期间内存中并不存在该常量。
- 使用 const 定义的常量是具有数据类型和作用域的常量,在程序运行期间内存中是存在该常量的符号标识的
-
2. 类型和安全检查不同
-
使用 #define 定义的常量不存在数据类型,从而在编译阶段,编译器不会对它进行类型检查
-
使用 const 定义的常量是具有数据类型的,在编译阶段,编译器会对它进行类型检查
-
3. 作用域检查不同
-
使用 #define 定义的常量没有作用域,它在定义之后的整个代码中都有效
-
使用 const 定义的常量具有作用域,只有在它所在的作用域内有效
-
4. 存储方式不同
-
使用 #define 定义的常量在符号表中不会有相应的条目。
-
使用 const 定义的常量会在符号表中有相应的条目,有助于调试和可读性。
使用 #define 与 const 这两种方式都可以用来定义常量,通常情况下,建议使用 const 关键字来定义常量,因为通过 const 关键字定义的常量,具有数据类型和作用域,编译器可以对它进行类型检测和作用域检查,而用 #define 定义的常量,仅在预编译阶段进行简单的文本替换,可能会导致一些没有预料到的问题。
相关文章:
C语言字面量和常量
目录 引言 1. 字面量 1.1 字符字面量 1.2 整型字面量 1.3 浮点字面量 2. 常量 2.1 使用预处理器指令 #define 定义常量 2.1.1 语法格式 2.1.2 使用举例 2.2 使用 const 关键字定义常量 2.3 使用 #define 和 const 定义常量的区别 引言 看了一些博文,有的文…...
视频结构化从入门到精通——行为分析类应用
行为分析类应用 1. 认识行为分析 监控/判断视频画面中目标的运动过程、携带属性等。从数据中自动识别、跟踪和理解人类或物体行为。 1. 车的行为分析应用 车辆行为分析主要用于监控和管理车辆的动态行为,广泛应用于智能交通、城市管理和安全监控。关键应用包括&…...
Redis的KeyExpirationEventMessageListener键过期监听器
MessageListener通过监听key过期的Redis keyspace通知,然后通过ApplicationEventPublisher发布RedisKeyExpiredEvent事件的模式进行事件监听和广播。 redis.conf地址:https://github.com/redis/redis/blob/unstable/redis.conf Redis官方地址࿱…...
MP4视频压缩,推荐这五大压缩操作
MP4视频压缩,在当今数字化的时代,视频已经成为我们日常生活和工作中不可或缺的一部分。然而,随着视频分辨率和长度的增加,MP4文件的大小也变得越来越大,这不仅占用了大量的存储空间,还使得传输和分享变得困…...
docker 安装NextERP
有很多方式: 一 docker sudo docker run -itd -p 8016:80 -v ERPNext_db:/var/lib/mysql -v ERPNext_sites:/home/frappe/frappe-bench/sites --name ERPNext lvxj11/erpnext:latest二 git clone https://e.coding.net/yuanerp/yuanerp/frappe_docker.gitcp exa…...
Android 存储之 SharedPreferences 框架体系编码模板
一、SharedPreferences 框架体系 1、SharedPreferences 基本介绍 SharedPreferences 是 Android 的一个轻量级存储工具,它采用 key - value 的键值对方式进行存储 它允许保存和读取应用中的基本数据类型,例如,String、int、float、boolean …...
弹性容器Flex中的自动外边距(Auto Margins) 的作用
最近在使用Flex布局时,遇到的一个情况: 有以下的代码: <div class"toolbox"><button id"decrease">-</button><span id"size">1</span><button id"increase">…...
C语言调用子函数时入/出栈(保护/恢复现场)全过程分析:以Cortex-M3为例
0 参考资料&工具 Cortex M3权威指南(中文).pdf keil5(用于仿真查看寄存器、栈变化)1 C语言调用子函数时出入/出栈(保护/恢复现场)全过程分析 使用C语言调用子函数是如何保护/恢复现场的呢?本文以Cortex-M3为例&a…...
理解Sigmoid激活函数原理和实现
Sigmoid 激活函数是一种广泛应用于机器学习和深度学习中的非线性函数,特别是在二分类问题中。它的作用是将一个实数值映射到(0, 1)区间,使得输出可以被解释为概率值,这在处理二分类问题时非常有用。 Sigmoid 函数的定义 Sigmoid 函数的数学…...
探秘DevSecOps黄金管道,安全与效率的完美融合
软件应用的安全性已成为企业和用户关注的焦点,DevSecOps作为一种将安全融入开发和运维全过程的理念和实践,旨在消除传统开发模式中安全被后置处理的弊端。DevSecOps黄金管道(Golden Pipeline)是实现这一理念的核心框架,…...
Redis的内存淘汰策略- volatile-lru
volatile-lru 策略简介 在 volatile-lru 策略下,当 Redis 的内存使用达到配置的上限(maxmemory)时,它会优先删除那些设置了过期时间的键,并且选择最近最少使用的键进行删除。LRU 算法的核心思想是,优先删除…...
HTTP和HTTPS的区别?哪一个更适合你的网站?
什么是 HTTP? HTTP(超文本传输协议)(Hypertext Transfer Protocol)它是一组允许网络浏览器与网络服务器(托管网站的计算机)进行通信的规则。 HTTP 使用请求-响应模型。 例如,当你…...
OpenAI SORA团队负责人 通往智能的方式 报告笔记
OpenAI SORA团队负责人 通往智能的方式 报告笔记 这个报告其实是2024年智源大会的主旨报告,OpenAI SORA和DALL-E团队负责人Aditya Ramesh给出的一段有关多模态大模型的报告。我去听了现场,感觉倍受启发,但是感觉很多并不能当场理解ÿ…...
006-Sleuth(Micrometer)+ZipKin分布式链路追踪
这里写目录标题 1 分布式链路追踪概述1.1 为什么会出现这个技术?需要解决哪些问题?1.2 在分布式与微服务场景下需要解决的问题 2 新一代Spring Cloud Sleuth:Micrometer2.1 官网重要提示2.1.1 新一代Sleuth2.1.2 官网2.1.3 说明2.1.3.1 老项目…...
AI模型:追求全能还是专精?-- 之6 语言复杂度类别(Category 0~3 类)和语言功能性类型(Type 0~Ⅲ 型)之2
Q17、我前面说过,语言复杂度的0~3级(Category 0~3)表示了语言的的上下文相关性 : 完全不相关, 单相关的 单词上下文, 双相关的句子上下文 全相关的文章上下文 。我准备翻译为 Context - irrelative /relati…...
20240907 每日AI必读资讯
大疆发布 DJI Neo 掌上 Vlog 无人机! - DJI Neo 是 DJI 迄今最轻、最小的无人机,无需遥控器,掌上起降即可轻松拍出主角大片… |135 克轻巧便携 丨零门槛掌上起降 丨AI 智能跟拍 ,一键成片 丨多种操控,丰富…...
深度学习基础--卷积基础模块
本节主要关注卷积神经网络发展过程中具有里程碑意义的基础模块,了解它们的原理和设计细节 1. 批归一化 在机器学习中,一般会假设模型的输入数据的分布是稳定的。如果这个假设不成立,即模型输入数据的分布发生变化,则称为协变量偏…...
视频智能分析打手机检测算法安防监控打手机检测算法应用场景、算法源码、算法模型介绍
随着智能手机的普及,手机已成为人们生活中不可或缺的一部分。然而,在某些场合,如驾驶、会议、学校课堂等,不当使用手机可能会导致安全隐患或干扰他人。因此,开发出一种能够准确识别并阻止不当使用手机的行为检测算法显…...
6.2图的存储及基本操作
6.2.1顺序存储 邻接矩阵法,用一个一维数组存储图中顶点信息,二维数组存储图中边的信息 无向图 1.无向图的邻接矩阵关于对角线对称,可采用压缩存储 2.边数为e,则邻接矩阵中1为2e; 3.第i行or 第i列非零元素之和恰好为顶点i的度数 4.判断是否有边用0,1 5. 有向图 1.关于对…...
Java语法全解析:掌握基本规则,打造稳固编程基础!
Java基本语法是编写Java程序的核心,它包括了数据类型、运算符、控制结构、类与对象等基本组成部分。这些语法要素共同构成了Java程序的基础框架,掌握它们是进行Java编程的前提。以下是Java基本语法的详细介绍: 数据类型 基本数据类型&#x…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
