【C语言】 关键字与用户标识符

关键字

关键字: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;
}
相关推荐
悟能不能悟2 小时前
grpc协议
开发语言
四维碎片2 小时前
【Qt】代理(Delegate)的使用
开发语言·qt
鹓于2 小时前
Excel一键生成炫彩二维码
开发语言·前端·javascript
froginwe112 小时前
MongoDB 固定集合详解
开发语言
m0_736919102 小时前
C++中的策略模式实战
开发语言·c++·算法
子春一2 小时前
Flutter for OpenHarmony:构建一个智能长度单位转换器,深入解析 Flutter 中的多字段联动、输入同步与工程化表单设计
开发语言·javascript·flutter
从此不归路2 小时前
Qt5 进阶【9】模型-视图框架实战:从 TableView 到自定义模型的一整套落地方案
开发语言·c++·qt
人道领域2 小时前
javaWeb从入门到进阶(SpringBoot基础案例2)
java·开发语言·mybatis
Stack Overflow?Tan902 小时前
c++constexpr
开发语言·c++