课程目标:

C 语言中的基本元素
常量、变量的概念和命名规则 ⭐⭐
变量的声明、初始化和定义 ⭐⭐⭐

先在Ubuntu下建立本章文件夹:

  1. b07@SB:~/c$ mkdir chapter4
  2. b07@SB:~/c$ cd chapter4
  3. b07@SB:~/c/chapter4$ mkdir bin include obj src
  4. b07@SB:~/c/chapter4$ ls
  5. bin include obj src

1. C 语言中的基本元素

常量和变量 - 图1

2. 常量、变量的概念和命名规则

必知概念在程序执行过程中,其值不发生改变的量称为常量。
在程序中,常量可以不经说明而直接使用。常量分类有两种:

  1. 直接常量(字面常量\字面值),其对应数据类型的常量包括:
    • 整型常量:12U0L-3
    • 实型常量:4.6F-1.23
    • 字符常量:'a', 'b'
    • 字符串常量:"Hello world!"
  2. 符号常量:符号常量定义成宏的形式: #define 符号常量 值,并且习惯上符号常量使用大写字母
    • 符号常量与变量不同,它的值在其作用域内不能改变,也不能再被赋值
    • 优点:含义清楚,能做到“一改全改”

常量示例:

#include <stdio.h>
#define PRICE 30  // 每次修改此处就行

int main() {
    // 10 和 0 都是字面常量
    int num = 10;
    int total = 0;
    // PRICE 是宏定义得到的符号常量
    total = num * PRICE;
    printf("total = %d\n", total);
    return 0;
}

必知概念在程序执行过程中,其值可以改变的量称为变量。


- 一个变量应该有一个名字(标识符),在内存中占据一定的存储单元。
- 变量定义必须放在变量使用之前,一般放在函数体的开头部分。
- 要区分变量名和变量值是两个不同的概念
image.png

必知概念用来标识变量名、符号常量名、函数名、数组名、类型名、文件名的有效字符序列称为标识符
标识符的命名规则:

  1. 可以由字母、数字和_(下划线)组合而成,必须以字母或_开头且区分大小写。
  2. 不能包含除_以外的任何特殊字符, 如 %、#、逗号、空白字符(换行符、空格和制表符)等。
  3. C 语言中的某些关键字(int 、float 等)称为保留字,具有特殊意义不能用作标识符。

案例:变量值修改过程如下

b07@SB:~/c/chapter4$ cat src/variable.c
#include <stdio.h>

int main() {
    // 定义变量并赋初值 6
    int a = 6;
    printf("Before a = %d\n", a);
    a = 9;
    printf("After a = %d\n", a);
    return 0;
}
b07@SB:~/c/chapter4$ gcc -Wall src/variable.c -o bin/variable
b07@SB:~/c/chapter4$ ./bin/variable
Before a = 6
After a = 9

3. 变量的声明、初始化和定义

因为 C 语言是静态类型语言,一个变量的类型在整个程序运行期间不能发生改变。
必知概念变量的声明主要是告诉编译器变量的类型和名字,在使用之前知道有这样一个变量的存在,它并不分配存储空间。其格式为数据类型 变量名;,例如int count;double ratio;
必知概念变量的定义和初始化是为变量分配存储空间,同时指明变量的类型和名字。其格式为数据类型 变量名 = 变量值;int count = 100; //在定义时进行初始化 :::info 变量声明和定义的区别:

  1. 关键点:是否分配存储空间?声明不分配存储空间,而定义分配。
  2. 严格意义上讲int a;属于定义式声明,也就说其分配存储空间,但是其值是随机的。而extern int a;才是引用式声明(将在后面讲到),因此统一将int a;int a = 100;都认为是“定义”。
  3. 在 C 语言中,变量有且只能有一次定义,而可以有多次声明! ::: 案例1:(定义式)声明与定义和初始化区别 ```shell b07@SB:~/c/chapter4$ cat src/declareDefine.c

    include

int main() { int a; // 定义式声明 printf(“Before assignment: a = %d\n”, a); // 对 a 进行赋值 a = 6; printf(“After assignment: a = %d\n”, a); int b = 2; // 定义变量 b 的同时赋初值 printf(“Define and initial: b = %d\n”, b); return 0; } b07@SB:~/c/chapter4$ gcc -Wall src/declareDefine.c -o bin/declareDefine src/declareDefine.c: In function ‘main’: src/declareDefine.c:5:2: warning: ‘a’ is used uninitialized in this function [-Wuninitialized] printf(“Before assignment: a = %d\n”, a); ^~~~~~~~~~~~ b07@SB:~/c/chapter4$ ./bin/declareDefine Before assignment: a = 0 After assignment: a = 6 Define and initial: b = 2

在此电脑上的`gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)`默认将未初始化的变量赋值为`0`。<br />**案例2**:变量不能多次定义
```shell

b07@SB:~/c/chapter4$ cat src/redeclaration.c
#include <stdio.h>

int main() {
    int a;  // 定义式声明
    int a;  // 表面上是声明,但是实际是重复定义

    int b = 2;  // 定义变量 b 的同时赋初值
    int b = 3;  // 重复定义
    return 0;
}
b07@SB:~/c/chapter4$ gcc -Wall src/redeclaration.c -o bin/redeclaration
src/redeclaration.c: In function ‘main’:
src/redeclaration.c:5:9: error: redeclaration of ‘a’ with no linkage
     int a;  // 表面上是声明,但是实际是重复定义
         ^
src/redeclaration.c:4:9: note: previous declaration of ‘a’ was here
     int a;  // 定义式声明
         ^
src/redeclaration.c:8:9: error: redefinition of ‘b’
     int b = 3;  // 重复定义
         ^
src/redeclaration.c:7:9: note: previous definition of ‘b’ was here
     int b = 2;  // 定义变量 b 的同时赋初值
         ^
src/redeclaration.c:8:9: warning: unused variable ‘b’ [-Wunused-variable]
     int b = 3;  // 重复定义
         ^
src/redeclaration.c:5:9: warning: unused variable ‘a’ [-Wunused-variable]
     int a;  // 表面上是声明,但是实际是重复定义

从上面看到编译器不允许重复定义变量,那么是不是extern int b;就可以随便用呢?

b07@SB:~/c/chapter4$ cat src/referenceDeclare.c
#include <stdio.h>

int main() {
    int a;  // 定义式声明
    extern int a;  // 引用式声明

    int b = 2;  // 定义变量 b 的同时赋初值
    extern int b;  // 引用式声明
    return 0;
}

b07@SB:~/c/chapter4$ gcc -Wall src/referenceDeclare.c -o bin/referenceDeclare
src/referenceDeclare.c: In function ‘main’:
src/referenceDeclare.c:5:16: error: extern declaration of ‘a’ follows declaration with no linkage
     extern int a;  // 引用式声明
                ^
src/referenceDeclare.c:4:9: note: previous declaration of ‘a’ was here
     int a;  // 定义式声明
         ^
src/referenceDeclare.c:8:16: error: extern declaration of ‘b’ follows declaration with no linkage
     extern int b;  // 引用式声明
                ^
src/referenceDeclare.c:7:9: note: previous definition of ‘b’ was here
     int b = 2;  // 定义变量 b 的同时赋初值
         ^
src/referenceDeclare.c:8:16: warning: unused variable ‘b’ [-Wunused-variable]
     extern int b;  // 引用式声明
                ^
src/referenceDeclare.c:5:16: warning: unused variable ‘a’ [-Wunused-variable]
     extern int a;  // 引用式声明

从报错信息看,该源代码需要链接其它模块才能够实现引用式声明。关于引用式声明的使用将在之后编译多个文件和作用域的时候提到。