关键字
关键字:C语言中规定的,有特殊用途的单词,称为关键字。关键字不能作为用户标识符。

const
关键字const用来定义常量,const修饰的局部变量(存储在栈空间)不可以通过变量名修改但是可以通过指针修改,const修饰的全局变量(存储在常量区)既不可以通过变量名修改也不可以通过指针修改。
用const修饰变量时,一定要给变量初始化,否则之后就不能再进行赋值了。
示例
c
const int x = 10; // 定义常量x,不可通过变量名修改
// x = 20; // 错误:不能修改常量
register
用register关键字修饰变量,就是编译程序时希望把该变量放到寄存器中,这样可以提高对该变量的访问速度。由前言可知,CPU访问寄存器的速度是高于访问内存的速度。当一个变量会被频繁调用时,可以用register去修饰变量,将变量保存在寄存器中,可以提升访问变量的速度。
示例
c
register int counter; // 建议编译器将counter放入寄存器
for (counter = 0; counter < 1000; counter++) {
// 频繁使用的循环变量
}
printf("Loop finished.\n");
volatile
volatile用于告诉编译器某个变量的值可能会被意外地改变,因此编译器不应该将相同的值缓存起来以供后续使用,而是应该每次都从内存中重新读取。这通常用于描述硬件寄存器或多线程共享的变量。
volatile可解释为"直接存取原始内存地址",确保本条指令不会被编译器的优化而忽略。
示例
c
#include <stdio.h>
volatile int flag = 0; // 可能被外部修改,禁止编译器优化
int main() {
while (flag == 0) {
// 每次循环都重新从内存读取flag的值
}
printf("Flag changed.\n");
return 0;
}
static
C语言中,变量存储位置分为栈、全局静态区、堆。
- 栈用来做函数调用,参数传递等,在程序的运行过程中是操作最频繁的数据区。
- 全局静态区,是变量一直存在于内存中,在程序整个运行过程中不会被销毁。
- 堆,是由操作系统维护的大空间内存伸缩区,进程可以主动向操作系统申请使用堆的存储,在程序运行过程中动态申请。
由static修饰的变量,其存储类型为全局静态区,变量在程序的整个运行过程中不会被销毁,并且只会被初始化1次。
被static修饰的局部变量生命周期是整个程序,但是作用域是和局部变量一样的,从定义开始,到最近的花括号结束。
全局变量默认对其他声明文件来说是可见,可用的。在一个文件引用了另一个文件之后就可以使用这个文件的全局变量。static会限定全局变量的可见域,只在本文件的任何地方可以访问,但是对于其他文件是不可见的。只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用。区别于一般的非静态函数(外部函数)。
函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。好处:
- 其他文件中可以定义相同名字的函数,不会发生冲突
- 静态函数不能被其他文件所用。
存储说明符auto,register,extern,static,对应两种存储期:自动存储期和静态存储期。
- auto和register对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块时被建立,它在该程序块活动时存在,退出该程序块时撤销。
- 关键字extern和static用来说明具有静态存储期的变量和函数。
静态局部变量在函数内定义,生存期为整个源程序,但作用域与自动变量相同,只能在定义该变量的函数内使用。退出该函数后, 尽管该变量还继续存在,但不能使用它。
示例
c
#include <stdio.h>
void counter() {
static int count = 0; // 静态局部变量,只初始化一次
count++;
printf("count = %d\n", count);
}
int main() {
counter(); // 输出1
counter(); // 输出2
counter(); // 输出3
return 0;
}
typedef
typedef用于为已有的数据类型创建一个新的名称。它可以在代码中为复杂的数据类型定义更简洁、易于理解的别名。typedef可以被用来创建新的类型名称,例如结构体、联合体、枚举等。
1.定义不一样
define定义后面不用加分号,并且它的别名在对象的前面
typedef需要加分号,并且它的别后面替换对象的前面
2.原理不一样
#define是预处理中的宏定义命令,在预处理时进行简单的字符串替换,不作正确性检查,只有在编译已被展开的源程序时才会发现可能的错误并报错
typedef是关键字,在编译时处理,有类型检查功能。它在自己的作用域内给一个已经存在的类型一个别名,但不能在一个函数定义里面使用typedef。typedef主要用来定义数组、指针、结构体等类型 ,不仅使程序书写简单,也使意义明确,增强可读性。
3.作用域不同
#define没有作用域的限制,只要是之前预定义过的宏,在以后的程序中都可以使用,因此使用#define之后为了防止错误,要将其解除掉。但是typedef有自己的作用域。
示例
c
#include <stdio.h>
typedef int Integer; // 为int创建别名
typedef int* IntPtr; // 为int*创建别名
int main() {
Integer a = 10;
IntPtr p = &a;
printf("a = %d, *p = %d\n", a, *p);
return 0;
}
#define
在C语言中,#define 指令用于定义宏,而条件编译则是通过 #ifdef、#ifndef、#if、#else 和 #endif 等指令来实现的。条件编译允许你根据不同的条件编译不同的代码块,这在处理不同平台、调试或配置选项时非常有用。
示例
c
#include <stdio.h>
#define PI 3.14159 // 定义常量宏
#define SQUARE(x) ((x) * (x)) // 定义函数宏
int main() {
double radius = 5.0;
double area = PI * SQUARE(radius);
printf("Area = %f\n", area);
return 0;
}
使用 #define 进行条件编译的基本示例
1.使用 #ifdef 和 #ifndef
c
#include <stdio.h>
// 定义一个宏
#define DEBUG
int main() {
#ifdef DEBUG
printf("Debug mode is enabled.\n");
#else
printf("Debug mode is disabled.\n");
#endif
return 0;
}
在这个示例中,如果定义了 DEBUG,程序将输出 "Debug mode is enabled."。如果没有定义 DEBUG,则输出 "Debug mode is disabled."。
2.使用 #if 和 #else
c
#include <stdio.h>
#define VERSION 2
int main() {
#if VERSION >= 2
printf("Version 2 or higher.\n");
#else
printf("Version lower than 2.\n");
#endif
return 0;
}
在这个示例中,VERSION 的值被用来决定编译哪个代码块。
3.使用 #ifndef 检查宏是否未定义
c
#include <stdio.h>
#ifndef MY_MACRO
#define MY_MACRO 100
#endif
int main() {
printf("MY_MACRO is defined as: %d\n", MY_MACRO);
return 0;
}
在这个示例中,如果 MY_MACRO 没有被定义,则将其定义为 100。
4.多个条件的组合
你还可以组合多个条件来进行更复杂的编译控制:
c
#include <stdio.h>
#define DEBUG
#define VERSION 2
int main() {
#ifdef DEBUG
printf("Debug mode is enabled.\n");
#endif
#if VERSION >= 2
printf("Version 2 or higher.\n");
#else
printf("Version lower than 2.\n");
#endif
return 0;
}
用户标识符
用户标识符:可以由用户自行规定,用于标识特定事物单词,称为用户标识符。
比如:变量名、函数名、枚举值、宏名、跳转标签都属于用户标识符。
用户标识符(或 变量名)的命名规范:
1.由英文字母(含大小写,且区分大小写) 、数字 、下划线_ 、美元符$组成
2.数字不能作为用户标识符中的首字符
3.不能使用关键字作为用户标识符
4.尽可能和含义相关
示例
c
#include <stdio.h>
int main() {
int student_age = 20; // 含义明确
float account_balance = 99.99;
char first_name = 'A';
printf("Age: %d\n", student_age);
printf("Balance: %.2f\n", account_balance);
printf("Initial: %c\n", first_name);
return 0;
}