c语言最佳实践之关键字

c语言的关键字包括:基本类型、void空类型、条件语句、循环语句、跳转指令、类型修饰符等。其中类型修饰符包括:const、extern、inline、static、volatile、register、restrict。下面按照功能划分,结合代码实例进行介绍。

关键字的功能说明如下表所示:

关键字功能描述
char字符类型,1个字节
short短整型类型,2个字节
int整型类型,4个字节
long长整型类型,8个字节
float浮点类型,4个字节
double双精度类型,8个字节
void空类型
auto自动变量
signed有符号数
unsigned无符号数
if条件语句
else条件语句的否定分支
switch开关语句
case开关语句的某个分支
default开关语句的其他分支
break跳出循环体
continue结束当次循环,继续下一轮
goto跳转指令
return子程序地址
for满足开始与终止条件的循环
while满足某个条件的循环
do先执行再循环
struct结构体
enum枚举
union联合体
sizeof测量数据类型长度
typedef给变量取别名
const常量
static静态变量/方法
extern外部变量
register寄存器变量
inline内联函数
volatile禁止指令重排序、内存可见
restrict类型限定符

一、基本类型与特殊类型

1、基本类型

c语言的基本类型包括:int、char、long、float、short、double。

2、void空类型

在c语言中,void为空类型,即可表示任意类型。常用在函数返回值,或void*表示空类型指针。

3、auto自动类型

auto用于自动类型推断,在c++11也有这个关键字。

4、有符号与无符号

有符号用signed表示,比如signed int表示范围-2147483648~2147483647。无符号用unsigned表示,从0开始。

二、条件语句

1、if...else判断

if用于判断某个条件是否成立,如果成立就进入if代码块,否则进入else代码块。

2、switch开关

switch结合case用做开关语句。需要注意的是,最后加上default,否则可能导致进入程序陷阱。示例代码如下:

    switch (num) {
        case 1:
            break;
        case 2:
            break;
        default:
            break;
    }

三、循环语句

1、for

for循环表达式块包括:开始条件、终止条件和自增/自减表达式。示例代码如下:

    for (int i = 0; i < 10; i++) {
        ...
    }

2、while

while循环表达式主要是判断是否满足条件,如果满足条件就继续执行,不满足则跳出循环。示例代码如下:

    while (num < 10) {
        num++;
    }

3、do...while

do/while循环与while循环不同的是,它先执行再判断是否满足条件。示例代码如下:

    do {
        num++;
    } while (num < 10);

四、跳转指令

1、break

break用于跳出循环体,示例代码如下:

    for (int i = 0; i < 10; i++) {
        if (i == 5) {
            break;
        }
    }

2、continue

continue用于跳过当次循环,继续执行下一轮。示例代码如下:

    while (i++ < 10) {
        if (i == 5) {
            continue;
        }
    }

3、goto

goto用于函数内的跳转,即短跳转指令。如果要支持函数外部跳转(长跳转),可以用setjmp。goto的示例代码如下:

void test() {
    int result = read();
    if (result < 0) {
        goto fail;
    }
    printf("result=%d", result);
fail:
    printf("something wrong...");
}

4、return

return用于函数返回。函数执行完成时,或者判断条件不成立时,如果函数有返回值,使用return进行返回。示例代码如下:

int test() {
    int result = read();
    if (result < 0) {
        return -1;
    }
    // something else
    return result;
}

五、结构体与枚举

1、struct结构体

结构体是数据结构的集合,可以存储不同的数据类型。需要注意的是,默认为内存对齐,使用最长的类型长度作为单位。示例代码如下:

struct Person {
    int age;
    char *name;
    float height;
    double weight;
};

2、enum枚举

枚举,顾名思义是枚举出同一类型的可能值。示例代码如下:

enum Fruit {
    APPLE,
    BANANA,
    ORANGE
};

3、union联合体

联合体是几个变量公用一个内存空间,这些变量可以是不同类型不同长度。但是,同一时刻,只能存储一个变量。示例代码如下:

union Type {
    int a;
    short b;
    float c;
    double d;
};

六、类型修饰符

1、const

const为常量修饰符,表示不会再修改的值,存放在常量存储区。可以用于修饰常量,也可以修饰函数参数,或者修饰函数返回值。示例代码如下:

// 常量
const int num = 10;
// 函数参数
void test(char* const val) {

}
// 函数返回值
const char* hello() {
    return "world";
}

2、extern

extern用于声明为外部全局变量,其他源文件也可以调用。首先在file_one.c声明变量:

int global_value = 0;

然后在file_one.h声明为外部变量:

extern int global_value;

 其他源文件file_other.c调用global_value变量:

#include "file_one.h"

void global_test() {
    global_value = 2;
}

3、inline

inline用于声明内联函数,作用是把代码和函数地址放在一起。优点是提高函数调用效率,缺点是增大目标文件的体积。建议使用场景为代码量比较少(10行以内),调用比较频繁的函数。

4、static

在c语言中,static用于声明静态变量、静态方法。存放区域是在静态/全局变量存储区。

5、volatile

volatile用于禁止编译器重排序,并且保证不同线程的内存可见同步。也就是具有可见性、有序性,不具有原子性,用在多线程场景或者底层编码。

6、register

register为寄存器变量,存放在CPU寄存器里,通过CPU寄存器寻址,而不是内存寻址。访问速度快、读写效率高,用于被程序频繁调用的使用场景。需要注意的是,register只能修饰局部变量或者函数形参,不能修饰全局变量或静态变量

7、restrict

restrict为类型限定符,只要是restrict修饰的指针,不能被除该指针以外的其他任何方式修改,无论是直接方式还是间接方式。示例代码如下:

    // 正确写法
    char* restrict str = "hello";
    // 错误写法1
    char restrict *str = "hello";
    // 错误写法2
    restrict char *str = "hello";

七、sizeof与typedef

1、sizeof

sizeof用于测量数据类型长度,比如在malloc申请内存时,或者计算数组长度。示例代码如下:

    // 计算需要申请内存大小
    char* data = (char*) malloc(10 * sizeof(char));
    // 计算数组长度
    int array[] = {1, 2, 3, 4, 5};
    int len = sizeof(array) / sizeof(array[0]);

2、typedef

typedef用于给变量类型取别名。作用是定义平台无关的数据类型,使用简单易懂的名称代替。我们来看看stdint.h头文件的源码:

// signed char取名为__int8_t
typedef signed char __int8_t;
typedef short __int16_t;
typedef int __int32_t;
#if defined(__LP64__)
typedef long __int64_t;
#else
typedef long long __int64_t;
#endif

// __int8_t取名为int8_t,所以int8_t最终指向signed char
typedef __int8_t      int8_t;
typedef __int16_t     int16_t;
typedef __int32_t     int32_t;
typedef __int64_t     int64_t;

八、其他关键字

1、alignof

alignof,用于查询运算类型的对齐要求。在c++中使用_Alignof,代码位于stdalign.h:

#ifndef __cplusplus
#define alignas _Alignas
#define alignof _Alignof
#endif

2、_Atomic

_Atomic用于声明变量为原子类型,包括bool、char、short、int、long等类型。具体可查看头文件stdatomic.h。

3、_Bool

_Bool用于表示布尔类型,0或1。具体可查看头文件stdbool.h,相关源码宏定义如下:

/* Don't define bool, true, and false in C++, except as a GNU extension. */
#ifndef __cplusplus
#define bool _Bool
#define true 1
#define false 0
#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
/* Define _Bool as a GNU extension. */
#define _Bool bool
#if __cplusplus < 201103L
/* For C++98, define bool, false, true as a GNU extension. */
#define bool  bool
#define false false
#define true  true
#endif
#endif

4、_Static_assert

_Static_assert用于静态断言。相关定义在stdassert.h头文件,宏定义如下:

#if !defined(__cplusplus) && __STDC_VERSION__ >= 201112L
# undef static_assert
# define static_assert _Static_assert
#endif

5、_Thread_local

_Thread_local,用于保存线程相关的变量。需要注意的是,该关键字只能用于修饰全局变量,不能修饰局部变量。示例代码如下:

// 正确用例
_Thread_local int a = 0;

void test() {
    // 错误用例
    _Thread_local int b = 0;
}

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

徐福记456

您的鼓励和肯定是我创作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值