4. 数据的模样:常量和变量

前几篇我们一直在和 Hello, World! 较劲,程序“说”了什么,却从没真正“记”住什么。如果程序只能输出固定的文字,那它不过是个复读机。要让程序有记忆力、能处理不同的数据,你就得和“变量”与“常量”交朋友了。

这篇文章里,你会第一次接触 C 语言的数据世界,了解如何给数据起名字、如何在内存里存放值、以及如何定义不会改变的量。这是往后所有复杂程序的地基——地基打得牢,才盖得起高楼。


一、变量是什么?一个容易理解的比喻

变量,就是一块带标签的内存抽屉。

想象你面前有一整面墙的小抽屉,每个抽屉能放下一个数字或一个字符。当你要存储数据时,你指着一个空抽屉说:“这个抽屉叫 age,里面放 25。”以后只要说 age,就能从那个抽屉里取出 25,也可以把它换成别的数字。

这就是变量的本质:

  • 你的程序向操作系统申请一小块内存。
  • 你给它取个名字(比如 age)。
  • 你往里面放数据。
  • 之后通过名字来读、来改。

名字本身不占内存,它只是“标签”,但抽屉(内存空间)会实际占用若干个字节。至于占多少字节,取决于你打算在抽屉里放什么类型的数据。


二、标识符命名规则——给抽屉起名字的规矩

在 C 语言里,变量名、函数名等统称为标识符。起名字不能随心所欲,必须遵守以下规则:

  1. 只能由字母(A-Za-z)、数字(0-9)和下划线(_)组成。
  2. 第一个字符不能是数字。 2ndValue 不合法,value2 合法。
  3. 区分大小写。 ageAgeAGE 是三个完全不同的变量。
  4. 不能使用 C 语言的关键字。 比如 intreturnifwhile 等已经被系统占了,你不能再拿来用。
  5. 长度没有硬性上限,但只有前 31 个字符保证有意义(现代编译器通常支持更长的有效长度,但过长的名字没必要)。

此外,还有一些强烈建议遵守的“好品味”

  • 用有意义的英文单词:agestudent_countmax_speed,不要用 ax1dsf(除非是临时循环变量)。
  • 变量名通常全小写,单词间用下划线连接(snake_case),或者用驼峰命名法(camelCase,如 studentCount)。在一个项目里保持一致即可,C 社区里 snake_case 更为常见。

三、声明与初始化——要抽屉、放东西

要使用变量,必须先声明后使用。声明的作用是告诉编译器:“我需要一个抽屉,请给我准备出足够的空间。”

声明的基本格式是:

类型 变量名;

比如:

int age;        // 声明一个整数变量 age
float score;    // 声明一个单精度浮点数变量 score
char grade;     // 声明一个字符变量 grade

这时候,抽屉是准备好了,但里面放的是不确定的垃圾值(之前留在那儿的随机数据)。直接读取未初始化的变量是危险且无意义的。

所以,最好在声明的同时给它一个初始值,这叫做初始化

int age = 25;
float score = 98.5;
char grade = 'A';

也可以一次声明多个同类型变量:

int x, y, z;                 // 三个未初始化的 int
int a = 1, b = 2, c = 3;     // 三个初始化了的 int

初始化形式还有一些灵活的地方,比如可以用常量表达式、甚至之前声明过的变量:

int a = 10;
int b = a + 5;   // b 初始化为 15
int c = b * 2;   // c 初始化为 30

注意:C 语言中,全局变量(在所有函数外面定义的)和静态局部变量如果不手动初始化,会被自动初始化为 0;而普通的局部变量(在函数内部定义的)则不会自动初始化,内容是垃圾值。初学阶段我们主要和局部变量打交道,所以请务必养成声明即初始化的习惯。


四、常量的两种面孔:const#define

有时候,程序里需要用到一些固定不变的值,比如圆周率、一天的小时数、最大用户数量。这些值在程序运行过程中不应该被修改。我们就可以用常量来表示它们。C 语言给了你两种主流的定义方式。

方式一:const 关键字

const 是“constant”的缩写,加在类型声明前面,意思是“这个抽屉里的东西只读,不能改”。

const int HOURS_PER_DAY = 24;
const float PI = 3.14159;

一旦用 const 声明并初始化后,试图修改它就会导致编译错误:

const int MAX = 100;
MAX = 200;   // 编译报错:assignment of read-only variable 'MAX'

const 定义常量的好处是它有明确的类型,编译器能做类型检查,用起来和普通变量一样安全,只是不能赋值。常量名通常全大写字母加下划线,这是一种约定,看到全大写就知道它是常量。

方式二:#define 预处理宏

我们之前学过 #include#define 也是预处理指令。它的用法是:

#define PI 3.14159
#define HOURS_PER_DAY 24

这行代码做了一件文本替换的事:在预处理阶段,编译器会把代码里所有出现 PI 的地方,原样替换成 3.14159。它不是变量,不占运行时内存,没有类型。

例如:

#include <stdio.h>
#define GREETING "你好,世界"

int main(void) {
    printf("%s\n", GREETING);
    return 0;
}

预处理后,printf 那行实际上变成了:

printf("%s\n", "你好,世界");

你可以用 gcc -E 查看替换后的结果,会看到 GREETING 消失了,只剩字符串。

#define 宏的优点:它不占用内存,执行时不需取址。缺点也很明显:没有类型检查,出现错误时编译器给出的信息可能很隐晦。比如:

#define PI 3.14159
// ...
int x = PI * 2;   // PI 是 double,这里会有隐式类型转换,编译器可能不会警告

如果 #define 用来定义复杂表达式,不加括号还可能导致诡异的错误(后面讲带参宏时会深入)。对于简单的数值常量或字符串常量,两种方式都可以,但初学阶段建议优先用 const,它更安全,更像“真正的”变量。


五、代码示例:常量与变量同台登场

我们写一个小程序,计算半径为 5 的圆的周长和面积,把所有学到的都用上:

#include <stdio.h>

#define PI 3.14159   // 宏定义常量

int main(void) {
    const int radius = 5;        // const 常量:半径
    float circumference;         // 未初始化变量,存放周长
    float area;                  // 存放面积

    circumference = 2 * PI * radius;   // 计算周长
    area = PI * radius * radius;       // 计算面积

    printf("半径: %d\n", radius);
    printf("周长: %.2f\n", circumference);
    printf("面积: %.2f\n", area);

    return 0;
}

%.2f 表示输出的浮点数保留两位小数,后面学格式化输入输出会详细解释。

运行输出:

半径: 5
周长: 31.42
面积: 78.54

试试把 const int radius 改成 int radius,再在下面加一行 radius = 10;,看看周长和面积的变化。你开始体会到:变量的威力在于可变,常量的价值在于安全。


六、常见错误与陷阱

1. 未声明就使用变量

int main(void) {
    a = 10;   // 错误!a 从未声明
    return 0;
}

编译报错:'a' undeclared。必须先声明后使用。

2. 声明了但未初始化就读取

int age;
printf("%d\n", age);   // 未定义行为,打印垃圾值

始终给变量一个初始值。

3. 试图修改 const 常量

const int MAX = 100;
MAX = 200;   // 编译错误

这很直观,错就错在去修改。

4. 宏定义里加等号或分号

#define PI = 3.14159;   // 错误!

宏替换后,PI 会被替换成 = 3.14159;,代码立刻就乱套了。#define 不需要 =,也不需要 ;


七、小结

今天我们了解了变量和常量的基础。变量让程序有了“记忆”,常量让固定值有了名字且更安全。你还学会了命名标识符的规矩,以及声明、初始化的正确姿势。

可能你会觉得这些内容有点“干”,但它们是构建一切程序的地基。就像学外语要先背单词,学音乐要练音阶,枯燥的基本功,决定了你以后能走多远。

下一篇文章,我们要进入数据类型的家族:intfloatdoublechar 都是什么样的抽屉,各占多少空间,彼此怎么转换。一个个认识它们,你会逐渐看清 C 语言内存世界的轮廓。


课后小练习

  1. 声明一个 float 变量存储你的身高(米),一个 int 变量存储你的年龄,分别初始化,然后用 printf 打印出来。(提示:%f 打印 float,%d 打印 int)
  2. const 定义一年中月份的数量(12),再用 #define 定义一周的天数(7),写程序计算一年大约有多少周,输出结果。
  3. 故意写一个未初始化变量并打印它的值,看看编译器是否会给出警告。如果有警告,读一读它说了什么。
  4. (思考题)下面这段代码哪里错了?
    #include <stdio.h>
    int main(void) {
        const int max_students;
        max_students = 45;
        printf("%d\n", max_students);
        return 0;
    }
    
    试着编译看结果,然后解释为什么。
代码转载自:https://pan.quark.cn/s/8ce4326d996e 对于在 CentOS 7 系统中修改网卡配置文件后无法使设置生效的情况,经过实践验证,可以通过使用 nmcli 命令来进行调整。完成修改之后,需要重新启动虚拟机以使更改生效,这样操作流程即告完成。如果设置仍然无法生效,则表明虚拟机在启动过程中所获取的 IP 地址配置并非针对 eth0,此时可以对其它网卡的配置文件进行修改或将其移除。在 CentOS 7 系统中,网络配置的管理机制与早期版本存在差异,主要体现为采用了 Network Manager 服务来负责网络接口的管理。在某些情形下,尽管修改了 `/etc/sysconfig/network-scripts` 目录下的 `ifcfg-eth0` 文件,但网络配置却未能即时生效。此类问题的发生通常源于 CentOS 7 采用了不同于以往的配置读取方法。接下来将具体阐述如何借助 nmcli 命令来处理这一挑战。 以 root 用户身份登录系统并打开终端界面。nmcli 是 Network Manager 提供的命令行界面工具,它支持在命令行环境下执行网络连接的建立、编辑、查询及管理任务。针对修改 eth0 网卡配置的需求,可以遵循以下步骤进行操作: 1. 导航至 `/etc/sysconfig/network-scripts` 目录: ``` cd /etc/sysconfig/network-scripts ``` 2. 检查该目录内是否存在 `ifcfg-eth0.bak` 文件,该备份文件可能是先前调整配置时遗留下来的,若存在可能造成冲突。若发现该文件,可以选择将其删除: ``` [root@localhost netw...
代码转载自:https://pan.quark.cn/s/46fd08fb879c 网管教程 从入门到精通软件篇 ★一。★详尽的xp修复控制台指令及其应用!!! 放入xp(2000)的光盘,安装时选择R,执行修复! Windows XP(涵盖 Windows 2000)的控制台指令是在系统遭遇某些意外状况时的一种极具效用的诊断、检测以及恢复系统功能的工具。笔者确实一直期望能够将这方面的指令进行归纳,此次由老范辛苦整理了这份极具价值的秘籍。 Bootcfg bootcfg 命令用于启动配置与故障恢复(对大多数计算机而言,即 boot.ini 文件)。 带有特定参数的 bootcfg 命令仅在运用故障恢复控制台时方可使用。能够在命令行界面下运用带有不同参数的 bootcfg 命令。 用法: bootcfg /default 设定默认引导选项。 bootcfg /add 向引导清单中增添 Windows 安装。 bootcfg /rebuild 重复整个 Windows 安装流程并让用户选择需添加的项目。 注意:运用 bootcfg /rebuild 之前,应先借助 bootcfg /copy 命令备份 boot.ini 文件。 bootcfg /scan 探查用于 Windows 安装的全部磁盘并展示结果。 注意:这些结果被静态存储,并用于当前会话。若在当前会话期间磁盘配置发生变动,为获取更新的探查结果,必须先重启计算机,然后再次探查磁盘。 bootcfg /list 列示引导清单中已有的项目。 bootcfg /disableredirect 在启动引导程序中禁用重定向。 bootcfg /redirect [ PortBaudRrate] |[ useBio...
代码下载链接: https://pan.quark.cn/s/fc524f791b68 AA制程,即Active Alignment,被理解为主动对准,是一种用于确定零部件装配中相对位置的方法。在摄像头封装阶段,涉及图像传感器、镜座、马达、镜头、线路板等多个部件的重复组装,而传统的封装设备如CSP及COB等,均是依据设备设定的参数进行零部件的移动装配,因而零部件的叠加误差会逐渐增大,最终在摄像头上表现为拍照最清晰的位置可能偏离画面中心、四边清晰度不均等现象。伴随智能手机其他高端电子产品的普及,摄像头模组的性能正日益受到重视。高分辨率、卓越的低光表现以及稳定视频输出是现代用户所期望的。在摄像头模组的制造环节,各部件的精准定位对成像质量具有决定性作用。因此,一种名为“AA制程”(Active Alignment)的前沿技术被开发出来,成为摄像头精密对准的核心技术。 AA制程,即Active Alignment,是一种在摄像头封装过程中应用的主动对准方法。该方法在多个组件装配阶段发挥作用,涵盖图像传感器、镜座、马达、镜头线路板等部件。传统的封装方式,例如CSP(Chip Scale Package)COB(Chip On Board),依赖于设备预设的参数进行组装,但随着组件数量的增加,误差也会累积,最终影响摄像头的表现。例如在成像质量上可能出现中心位置偏移、四角清晰度不一致等问题。 AA制程技术的核心在于实时监测与主动调整。在组装过程中,它借助先进的检测设备持续监控半成品的状态,并根据实时信息对组装部件进行精确修正,从而显著降低装配误差。通过这种技术,能够确保摄像头模组中各组件的相对位置准确无误,从而使得最终的成像效果更加稳定,特别是在中心区域四角的清晰度上...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值