C语言字面量和常量

news2024/9/20 18:52:12

目录

引言

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);    // A

    return 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码:65
    char c2 = 0101;   // 八进制
    char c3 = 0x41;   // 十六进制
    printf("%c,%c,%c\n", c1, c2, c3);    // A,A,A

    return 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,A

    return 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, 8
    printf("%d, %d\n", sizeof(.01f), sizeof(0.01f));        // 4, 4
    printf("%.2f, %.2f\n", .01, 0.01);                      // 0.01, 0.01
    printf("%d, %d\n", sizeof(0.), sizeof(0.f));            // 8, 4
    printf("%d\n", sizeof(3.14));                           // 8
    printf("%d, %d\n", sizeof(3.14f), sizeof(3.14F));       // 4, 4
    printf("%d, %d\n", sizeof(3.14e0), sizeof(3.14E0));     // 8, 8
    printf("%d, %d\n", sizeof(3.14e0f), sizeof(3.14E0F));   // 4, 4
    printf("%d, %d\n", sizeof(0e0), sizeof(0e0f));          // 8, 4
    return 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(""));   // 1
    return 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 定义的常量,仅在预编译阶段进行简单的文本替换,可能会导致一些没有预料到的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2111914.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HarmonyOS(55) error: install releaseType target not same 解决方案

releaseType not same 问题现象解决方法参考资料 问题现象 在DevEco Studio 链接真机运行时发现如下错误&#xff1a; 09/06 08:40:45:905: Install Failed: error: failed to install bundle. code:9568258 error: install releaseType not same. 09/06 08:40:45:966: View …

集成电路学习:什么是SDK软件开发工具包

SDK&#xff1a;软件开发工具包 SDK&#xff0c;即Software Development Kit&#xff08;软件开发工具包&#xff09;&#xff0c;是一套由软件提供商或其他组织提供的开发工具集合。这些工具旨在帮助开发者更快速、更便捷地创建、测试和部署软件应用程序。以下是对SDK的详细解…

全国计算机二级考试C语言篇3——选择题

C语言部分——C语言概述 1.程序模块化的优点 程序模块化的优点在于它可以使程序的开发、维护和复用变得更简单。下面是一些主要的优点&#xff1a; 降低复杂度&#xff1a;模块化可以将复杂的问题分解成更小的、更易管理的部分。 可维护性&#xff1a;模块化使得代码更易于维护…

前缀列表(ip-prefix)配置

一. 实验简介 本来前缀列表是要和访问控制列表放在一起讲的&#xff0c;但是这里单拎出来是为了更详细的讲解两者的区别 1.前缀列表针对IP比访问控制更加灵活。 2.前缀列表在后面被引用时是无法对数据包进行过滤的 实验拓扑 二. 实验目的 R4路由器中只引入子网LoopBack的…

DFS算法专题(一)——二叉树中的深搜【回溯与剪枝的初步注入】

目录 1、DFS算法简介 2、算法实战应用【leetcode】 2.1 计算布尔二叉树的值 2.1.1 算法原理 2.1.2 算法代码 2.2 求根节点到叶节点数字之和 2.2.1 算法原理 ​2.2.2 算法代码 2.3 二叉树剪枝 2.3.1 算法原理 2.3.2 算法代码 2.4 验证二叉搜索树 2.4.1 算法原理 …

紫微斗数算法的实现流程

题外话 我想了又想大凡能够修炼成绝世高手的都是“魔鬼”。只有魔鬼才会纯粹的“敢贪&#xff0c;敢嗔&#xff0c;敢痴”。 你我都困在了敢字。程序猿拿起拿锋利的刀&#xff0c;解构世间的一切吧&#xff01;最近看西游有感而发。 “联系是普遍存在的&#xff0c;规律是客观…

我开源了我的新闻网站项目

&#x1f389; 前言 暑假时写了一个Web项目&#xff0c;感觉做的还是有模有样的&#xff0c;不仅做了前端&#xff0c;还加了后端并连了数据库。最近也是将它开源了&#xff0c;一来是为了熟悉一下Github流程和Git使用命令&#xff0c;二来也是想和大家分享一下自己的成果&…

[阅读笔记]《解读基金—我的投资观与实践》— 季凯帆

&#x1f4e2;博客主页&#xff1a;https://loewen.blog.csdn.net&#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;本文由 丶布布原创&#xff0c;首发于 CSDN&#xff0c;转载注明出处&#x1f649;&#x1f4e2;现…

java环境变量怎么调

java 环境变量配置是设置系统查找和使用 java 工具的路径。通过以下步骤配置&#xff1a;安装 java jdk。设置 path 变量&#xff0c;添加 java 可执行文件目录路径。设置 java_home 变量&#xff0c;指定 jdk 安装目录路径。验证配置&#xff0c;运行 "java -version&quo…

io本质+io效率本质,5种io模型(介绍,异步/同步区别,阻塞/非阻塞区别)

目录 5种io模型 io引入 io的本质 io效率的本质 模型引入 以钓鱼为例 效率最高的方式 异步io和同步io的区别 阻塞式和非阻塞式io的区别 介绍 阻塞式io ​编辑 非阻塞式io ​编辑 信号驱动式io ​编辑 多路转接/复用 ​编辑 异步io 5种io模型 io引入 io的本质…

【鸿蒙HarmonyOS NEXT】页面和自定义组件生命周期

【鸿蒙HarmonyOS NEXT】页面和自定义组件生命周期 一、环境说明二、页面和自定义组件生命周期三、示例代码加以说明四、小结 一、环境说明 DevEco Studio 版本&#xff1a; API版本&#xff1a;以12为主 二、页面和自定义组件生命周期 需要明确几个概念&#xff1a; 页面…

0to1使用Redis实现“登录验证”次数限制

1 引言 系统为了避免密码遭到暴力破解&#xff0c;通常情况下需要在登录时&#xff0c;限制用户验证账号密码的次数&#xff0c;当达到一定的验证次数后&#xff0c;在一段时间内锁定该账号&#xff0c;不再验证。本章将用几行代码实现该功能&#xff0c;完整代码链接在文章最…

Markdown全兼容,MarkText打造专业文档新体验

前言 在科技的洪流中&#xff0c;我们不仅是见证者&#xff0c;更是创造者。它赋予我们力量&#xff0c;将遥不可及的梦想拉近至指尖&#xff0c;让生活的每一刻都充满无限可能。随着数字化内容的爆炸性增长&#xff0c;Markdown作为一种轻量级标记语言&#xff0c;凭借其简洁…

tekton构建标准ci(clone repo, test, build push img)

场景介绍 我们在上一篇文章中构建了一个最简单的ci&#xff0c;接下来我们对我们的github的项目构建一个较标准的ci。 Tekton简介&#xff0c;安装和构建最简单ci/cd-CSDN博客文章浏览阅读239次&#xff0c;点赞2次&#xff0c;收藏2次。本文介绍了tekton是什么&#xff0c;如…

vsftpd配置用户和密码让其他客户端连接

一、第一个主机:vsftpd下载及配置 前置准备: #卸载防火墙 yum -y remove firewalld #为了不让防火墙有影响&#xff0c;iptables配置也清空 iptables -F vim /etc/selinux/conf SELINUXdisabled #主要是把它改为disabled或者permissive SELINUXTYPEtargeted #重启linux让seli…

[Web安全 网络安全]-安全法规 网络基础 信息收集

文章目录&#xff1a; 一&#xff1a;网络安全法规 二&#xff1a;计算机网络 1.计算机网络的组成 2.网络分层模型&#xff08;OSI七层 TCP/IP四层&#xff09; 3.通信协议 IP协议 UDP协议/TCP协议 TCP协议 UDP协议 区别 HTTP协议/HTTPS协议 HTTP协议 HTTPS协议…

RedissonClient 分布式队列工具类

注意&#xff1a;轻量级队列可以使用工具类&#xff0c;重量级数据量 请使用 MQ 本文章基于redis使用redisson客户端实现轻量级队列&#xff0c;以及代码、执行结果演示 一、常见队列了解 普通队列&#xff1a;先进先出&#xff08;FIFO&#xff09;&#xff0c;只能在一端添…

【网络安全 | 甲方建设】SaaS平台、Jira工具及Jenkins服务器

原创文章,不得转载。 文章目录 SaaS平台友好性Jira友好性Jenkins友好性SaaS平台 SaaS,全称为 “Software as a Service”(软件即服务),是一种基于云计算的软件交付模型。在这种模型中,软件不需要用户在本地安装和维护,而是通过互联网访问和使用。软件通常由服务提供商托…

RLC(电阻、电感、电容)

RLC&#xff08;电阻、电感、电容&#xff09; 目录一、两个电阻&#xff08;R1&#xff0c;R2&#xff09;&#xff0c;电容&#xff08;C1&#xff0c;C2&#xff09;的串联/并联公式&#xff1f;二、请画出这个1ms&#xff0c; 1V的Vin脉冲信号在Vout端的大致图像1.电路图2.…

中秋猜灯谜_猜字谜小程序源码,无需服务器

这款小程序搭建是免服务器和域名的&#xff0c;serverless&#xff0c;没有后端; 无需设置合法域名的!上传就可以使用; 只需要使用微信开发者工具打开源码然后上传审核就可以了! 这款小程序其实比较简洁&#xff0c;分两种模式青铜模式(普通)和王者模式(困难)&#xff0c;猜…