C语言关键字

C语言关键字

目录

基本数据类型关键字

关键字说明示例
void表示无类型,用于函数返回值或参数void func(void);
char字符类型,通常占1字节char c = 'A';
int整型,通常为4字节int i = 10;
float单精度浮点型,4字节float f = 3.14f;
double双精度浮点型,8字节double d = 3.14159;

类型修饰关键字

关键字说明示例
short短整型,通常为2字节short s = 100;
long长整型,至少4字节long l = 1000000L;
signed有符号类型(默认)signed int i = -10;
unsigned无符号类型,不能表示负数unsigned int u = 10U;
const声明常量,值不可更改const int MAX = 100;
volatile告知编译器该变量可能被异步修改volatile int flag;

存储类关键字

关键字说明示例
auto自动存储(局部变量默认)auto int var = 10;
register建议将变量存放在寄存器中register int counter;
static使局部变量保持其值;限制全局变量/函数作用域static int count = 0;
extern声明一个在其他文件定义的变量extern int global_var;

控制流关键字

关键字说明示例
if条件语句if (x > 0) { /* 代码块 */ }
else与if配合使用,表示否则if (x > 0) { /* 代码块 */ } else { /* 代码块 */ }
switch多重分支语句switch (option) { case 1: /* 代码 */ break; }
case用于switch语句中的分支标签case 1: printf("Option 1"); break;
defaultswitch语句的默认分支default: printf("Invalid option");
for循环语句for (i=0; i<10; i++) { /* 代码块 */ }
while当条件为真时循环执行while (condition) { /* 代码块 */ }
do先执行后判断的循环do { /* 代码块 */ } while (condition);
break跳出当前循环或switch语句break;
continue跳过当前循环的剩余部分continue;
goto无条件跳转到标签处(不推荐使用)goto label; /* ... */ label: /* 代码 */
return从函数返回return value;return;

结构化类型关键字

关键字说明示例
struct定义结构体类型struct Person { char name[50]; int age; };
union定义共用体类型,成员共享内存union Data { int i; float f; char str[20]; };
enum定义枚举类型enum Color { RED, GREEN, BLUE };
typedef为现有类型创建别名typedef unsigned int uint;

其他关键字

关键字说明示例
sizeof返回类型或表达式的字节大小size_t size = sizeof(int);

C99/C11新增关键字

关键字说明示例
inline建议编译器内联展开函数inline int max(int a, int b) { return a > b ? a : b; }
restrict指示指针是访问该对象的唯一方式void copy(int* restrict dst, int* restrict src, int n);
_Bool布尔类型(C99)_Bool flag = 1;
_Complex复数类型(C99)_Complex double c = 1.0 + 2.0 * I;
_Imaginary虚数类型(C99)_Imaginary double im = 2.0 * I;
_Atomic原子类型(C11)_Atomic int shared_counter;
_Thread_local线程局部存储(C11)_Thread_local int thread_id;
_Static_assert编译时断言(C11)_Static_assert(sizeof(int) == 4, "Int must be 4 bytes");
_Noreturn表明函数不会返回(C11)_Noreturn void exit_program(void);
_Generic类型泛型表达式(C11)_Generic(x, int: "int", float: "float", default: "other")

关键字的使用示例

数据类型示例

int main() {
    // 基本数据类型
    char c = 'A';          // 字符
    int i = 42;            // 整数
    float f = 3.14f;       // 单精度浮点数
    double d = 2.71828;    // 双精度浮点数
    
    // 类型修饰符
    unsigned int ui = 100;  // 无符号整数
    long int li = 1000000L; // 长整数
    const float pi = 3.14f; // 常量(不可修改)
    
    return 0;
}

控制流示例

int max(int a, int b) {
    if (a > b) {
        return a;
    } else {
        return b;
    }
}

void print_day(int day) {
    switch (day) {
        case 1:
            printf("Monday");
            break;
        case 2:
            printf("Tuesday");
            break;
        // ...其他情况...
        default:
            printf("Invalid day");
    }
}

void count_to_ten() {
    for (int i = 1; i <= 10; i++) {
        printf("%d ", i);
    }
    
    int j = 1;
    while (j <= 10) {
        printf("%d ", j);
        j++;
    }
    
    int k = 1;
    do {
        printf("%d ", k);
        k++;
    } while (k <= 10);
}

存储类示例

// 文件作用域的静态变量(仅在当前文件可见)
static int counter = 0;

void increment() {
    // 函数作用域的静态变量(保持值)
    static int calls = 0;
    calls++;
    counter++;
    printf("Function called %d times, counter = %d\n", calls, counter);
}

// extern关键字用于声明外部变量
extern int global_variable;

结构体和共用体示例

// 定义结构体
struct Person {
    char name[50];
    int age;
    float height;
};

// 使用typedef创建类型别名
typedef struct {
    int x;
    int y;
} Point;

// 定义共用体(所有成员共享同一块内存)
union Data {
    int i;       // 4字节
    float f;     // 4字节
    char str[8]; // 8字节
}; // 整个共用体大小为8字节(最大成员的大小)

// 定义枚举
enum Color {
    RED,    // 0
    GREEN,  // 1
    BLUE    // 2
};

关键字深入解析

const 关键字详解

const 是一个类型限定符,用于声明"只读"变量或参数,表示其值在初始化后不应被修改。

用途和特性:

  1. 创建只读变量:防止变量被意外修改

    const int MAX_USERS = 100;  // 声明常量
    MAX_USERS = 200;  // 编译错误:不能修改const变量
    
  2. 只读函数参数:表明函数不会修改传入的参数

    void print_array(const int arr[], int size) {
        // 函数内不能修改arr指向的内容
        // arr[0] = 100;  // 编译错误
    }
    
  3. 只读指针与指针常量

    // 指向常量的指针(不能通过此指针修改目标值)
    const int *ptr1 = &value;
    // *ptr1 = 100;  // 编译错误
    ptr1 = &other_value;  // 可以更改指针指向
    
    // 常量指针(指针本身不能更改指向)
    int * const ptr2 = &value;
    *ptr2 = 100;  // 允许
    // ptr2 = &other_value;  // 编译错误
    
    // 指向常量的常量指针(两方面都不能修改)
    const int * const ptr3 = &value;
    
  4. 与类型定义结合

    const struct Point origin = {0, 0};  // 常量结构体
    

最佳实践:

  • 对不应修改的变量使用const可增强代码健壮性
  • 函数参数中使用const可明确表达设计意图
  • 结合指针使用时注意const位置的不同含义

volatile 关键字详解

volatile 告知编译器变量可能在程序控制外被改变,防止编译器优化掉对该变量的操作。

用途和特性:

  1. 硬件寄存器访问

    volatile uint32_t *gpio_port = (uint32_t*)0x40020000;  // 指向外设寄存器
    *gpio_port = 0x01;  // 这个写入不会被优化掉
    
  2. 多线程共享变量

    volatile int shared_flag = 0;
    
    // 线程1
    while (!shared_flag) {
        // 等待另一线程修改标志
        // 没有volatile,编译器可能优化为无限循环
    }
    
  3. 信号处理程序中的变量

    volatile sig_atomic_t signal_received = 0;
    
    void signal_handler(int sig) {
        signal_received = 1;
    }
    
  4. 结合const使用

    // 不能被代码修改,但可能被外部因素改变的变量
    volatile const int sensor_value = 0;
    

注意事项:

  • volatile不保证原子性或内存顺序,不应替代同步机制
  • 现代多线程程序应使用适当的同步原语而非仅依赖volatile
  • 主要用于直接硬件交互和特殊内存映射区域

static 关键字详解

static 在不同上下文中有不同的含义,影响变量的生命周期和可见性。

1. 局部变量中的static:

  • 使变量在函数调用之间保持其值
  • 仅初始化一次(首次调用时)
  • 存储在静态数据区而非栈上
void counter() {
    static int count = 0;  // 仅在第一次调用时初始化
    count++;
    printf("Called %d times\n", count);
}

int main() {
    counter();  // 输出: Called 1 times
    counter();  // 输出: Called 2 times
    counter();  // 输出: Called 3 times
    return 0;
}

2. 全局变量/函数中的static:

  • 将作用域限制在当前文件内
  • 防止其他文件访问该标识符
  • 实现模块的封装和隐藏实现细节
// file1.c
static int counter = 0;  // 仅在file1.c中可见
static void helper() {   // 仅在file1.c中可访问
    counter++;
}

void public_function() {
    helper();
    printf("Counter: %d\n", counter);
}

// file2.c
extern int counter;  // 错误:无法访问file1.c中的静态变量
helper();  // 错误:无法访问file1.c中的静态函数

3. 类中的static(C++相关,C中无此用法)

最佳实践:

  • 使用static局部变量替代全局变量,减少全局命名空间污染
  • 使用static限制不需要导出的函数和变量,提高封装性
  • 注意静态变量在多线程环境中可能需要同步机制

extern 关键字详解

extern 用于声明外部变量或函数,表示其定义在其他地方(通常是另一个源文件)。

用途和特性:

  1. 引用其他文件中的全局变量

    // file1.c
    int global_counter = 0;  // 定义
    
    // file2.c
    extern int global_counter;  // 声明
    void increment() {
        global_counter++;  // 使用file1.c中定义的变量
    }
    
  2. 引用外部函数(通常隐式extern):

    // file1.c
    void helper_function() {
        // 实现
    }
    
    // file2.c
    extern void helper_function();  // 声明
    // 或直接:void helper_function();  // extern可省略
    
  3. 与const结合使用

    // file1.c
    extern const int MAX_USERS;  // 常量声明
    
    // file2.c
    const int MAX_USERS = 100;  // 常量定义
    
  4. 指定链接属性

    extern "C" {  // 在C++中指定使用C链接约定
        void c_function();
    }
    

注意事项:

  • extern只是声明而非定义,不分配存储空间
  • 全局变量只应在一个文件中定义(初始化)
  • 头文件中通常使用extern声明全局变量,在源文件中定义
  • extern "C"是C++语法,用于避免C++名称修饰

inline 关键字详解

inline 向编译器提供将函数内联展开的建议,用于优化小而频繁调用的函数。

用途和特性:

  1. 减少函数调用开销

    inline int max(int a, int b) {
        return a > b ? a : b;
    }
    
    void process() {
        int result = max(5, 10);  // 可能被编译为:int result = 5 > 10 ? 5 : 10;
    }
    
  2. C99中的作用

    • 允许在多个翻译单元中定义同一个函数
    • 提供外部链接的内联函数
  3. 内联函数vs宏

    // 宏定义
    #define MAX(a, b) ((a) > (b) ? (a) : (b))
    
    // 内联函数
    inline int max(int a, int b) {
        return a > b ? a : b;
    }
    

注意事项:

  • inline仅为建议,编译器可能忽略
  • 复杂函数即使标记为inline也可能不被内联
  • 过度使用可能导致代码膨胀
  • 现代编译器通常能自动决定内联,不必显式标记
  • C99标准要求同时使用static或extern

#define 指令详解

#define 是预处理器指令而非关键字,用于定义宏。

用途和特性:

  1. 简单常量定义

    #define PI 3.14159
    #define MAX_BUFFER_SIZE 1024
    #define DEBUG_MODE
    
  2. 带参数的宏

    #define SQUARE(x) ((x) * (x))
    #define MAX(a, b) ((a) > (b) ? (a) : (b))
    #define SAFE_FREE(p) do { free(p); p = NULL; } while(0)
    
  3. 条件编译

    #define DEBUG
    
    #ifdef DEBUG
        printf("Debug info: %d\n", value);
    #endif
    
    #if defined(WIN32)
        // Windows特定代码
    #elif defined(__linux__)
        // Linux特定代码
    #else
        // 其他平台代码
    #endif
    
  4. 字符串化和连接

    #define STRINGIFY(x) #x         // 转为字符串
    #define CONCAT(a, b) a##b       // 符号连接
    
    char *str = STRINGIFY(hello);   // "hello"
    int xy = 10;
    int value = CONCAT(x, y);       // 等同于 int value = xy;
    

注意事项:

  • 宏没有类型检查,潜在风险高于内联函数
  • 复杂宏需要谨慎括号处理
  • do-while(0)结构可创建复合语句宏
  • 避免在宏中使用有副作用的表达式
  • 宏名通常全大写以区分

struct 关键字详解

struct 用于定义复合数据类型,将多个不同类型的数据组合在一起。

用途和特性:

  1. 基本结构体定义和使用

    struct Person {
        char name[50];
        int age;
        float height;
    };
    
    struct Person person1 = {"John", 30, 1.75};
    printf("Name: %s\n", person1.name);
    person1.age = 31;  // 修改成员
    
  2. 结构体指针

    struct Person *ptr = &person1;
    printf("Age: %d\n", ptr->age);  // 使用箭头操作符
    ptr->height = 1.80;  // 通过指针修改成员
    
  3. 嵌套结构体

    struct Address {
        char street[100];
        char city[50];
        int zip_code;
    };
    
    struct Employee {
        struct Person person;  // 嵌套结构体
        struct Address address;
        int employee_id;
    };
    
    struct Employee emp;
    emp.person.age = 25;
    strcpy(emp.address.city, "New York");
    
  4. 结构体数组

    struct Person team[10];
    team[0].age = 28;
    strcpy(team[1].name, "Alice");
    
  5. 自引用结构体(链表等)

    struct Node {
        int data;
        struct Node *next;  // 自引用
    };
    
  6. 位域

    struct Flags {
        unsigned int ready:1;     // 1位
        unsigned int active:1;    // 1位
        unsigned int status:3;    // 3位
    };  // 仅占用1字节,而不是3个int
    

最佳实践:

  • 使用typedef简化结构体使用
  • 大结构体传参时使用指针避免拷贝开销
  • 考虑内存对齐对结构体大小的影响
  • 定义初始化和清理函数处理复杂结构体

union 关键字详解

union 定义一种特殊数据类型,多个成员共享同一内存空间,大小由最大成员决定。

用途和特性:

  1. 基本定义和使用

    union Data {
        int i;        // 4字节
        float f;      // 4字节
        char str[8];  // 8字节
    };  // 总大小为8字节
    
    union Data data;
    data.i = 123;
    printf("Integer: %d\n", data.i);
    data.f = 3.14;  // 覆盖了整数值
    printf("Float: %f\n", data.f);
    
  2. 内存节约

    // 不使用union:可能需要24字节
    struct Value1 {
        int type;
        int int_val;
        float float_val;
        char *str_val;
    };
    
    // 使用union:仅需12字节
    struct Value2 {
        int type;
        union {
            int int_val;
            float float_val;
            char *str_val;
        } data;
    };
    
  3. 位操作和类型转换

    union FloatInt {
        float f;
        uint32_t i;
    };
    
    union FloatInt val;
    val.f = 3.14;
    printf("Bit representation: 0x%08X\n", val.i);
    
  4. 网络字节序转换

    union {
        uint32_t value;
        uint8_t bytes[4];
    } converter;
    
    converter.value = 0x12345678;
    printf("Byte0: 0x%02X\n", converter.bytes[0]);  // 查看字节序
    

注意事项:

  • 在同一时刻只有一个成员是"活动的"
  • 使用非活动成员读取值是未定义行为
  • 使用类型标记跟踪当前活动成员
  • 不同编译器可能有不同的内存对齐规则

enum 关键字详解

enum 用于定义枚举类型,创建一组命名的整型常量。

用途和特性:

  1. 基本定义和使用

    enum Day {
        MONDAY,     // 0
        TUESDAY,    // 1
        WEDNESDAY,  // 2
        THURSDAY,   // 3
        FRIDAY,     // 4
        SATURDAY,   // 5
        SUNDAY      // 6
    };
    
    enum Day today = WEDNESDAY;
    if (today == WEDNESDAY) {
        printf("It's Wednesday!\n");
    }
    
  2. 指定值

    enum Status {
        ERROR = -1,
        SUCCESS = 0,
        PENDING = 100,
        RUNNING,  // 101
        FINISHED  // 102
    };
    
  3. 作为switch的选择器

    enum Operation { ADD, SUBTRACT, MULTIPLY, DIVIDE };
    
    int calculate(int a, int b, enum Operation op) {
        switch (op) {
            case ADD: return a + b;
            case SUBTRACT: return a - b;
            case MULTIPLY: return a * b;
            case DIVIDE: return b != 0 ? a / b : 0;
            default: return 0;
        }
    }
    
  4. 位标志

    enum FilePermission {
        READ = 1 << 0,    // 0001
        WRITE = 1 << 1,   // 0010
        EXECUTE = 1 << 2  // 0100
    };
    
    int permissions = READ | WRITE;  // 0011
    if (permissions & EXECUTE) {
        printf("Has execute permission\n");
    }
    

最佳实践:

  • 使用enum替代魔数常量提高可读性
  • 枚举类型本质上是整型,不提供类型安全
  • 考虑位掩码应用场景
  • C中enum大小由实现决定,通常为int大小

_asm 关键字详解(编译器扩展)

_asmasm 是编译器扩展,允许在C代码中嵌入汇编指令。不同编译器语法可能不同。

用途和特性:

  1. Microsoft Visual C++语法

    void delay_loop() {
        _asm {
            mov ecx, 1000000  ; 循环计数
        loop_start:
            nop               ; 无操作
            dec ecx           ; 计数器减1
            jnz loop_start    ; 不为零则循环
        }
    }
    
  2. GCC语法

    void critical_section() {
        asm volatile (
            "cli\n\t"         /* 禁止中断 */
            "mov eax, [data]\n\t"
            "add eax, 10\n\t"
            "mov [data], eax\n\t"
            "sti"             /* 允许中断 */
            : /* 输出操作数 */
            : /* 输入操作数 */
            : "eax", "memory" /* 被修改的寄存器 */
        );
    }
    
  3. 读取CPU特殊寄存器

    unsigned long read_cr0() {
        unsigned long cr0;
        asm volatile ("mov %%cr0, %0" : "=r" (cr0));
        return cr0;
    }
    
  4. 优化关键性能代码

    // 使用SSE指令优化浮点运算
    void vector_add(float *a, float *b, float *result, int size) {
        asm volatile (
            "movups (%0), %%xmm0\n\t"
            "movups (%1), %%xmm1\n\t"
            "addps %%xmm1, %%xmm0\n\t"
            "movups %%xmm0, (%2)"
            :
            : "r" (a), "r" (b), "r" (result)
            : "xmm0", "xmm1", "memory"
        );
    }
    

注意事项:

  • 内联汇编不可移植,绑定特定架构
  • 现代编译器优化能力强,手写汇编可能不如编译器优化
  • 适用于访问硬件寄存器、实现原子操作等
  • 不同编译器语法差异大
  • 需要深入了解目标处理器架构
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值