C语言全部关键字解析

news2025/1/11 4:02:20

前言

C语言具有以下关键字:
这些关键字如下:

autobreakcase
charconstcontinue
defaultdodouble
elseenumextern
floatforgoto
ifintlong
registerreturnshort
signedsizeofstatic
structswitchtypedef
unionunsignedvoid
volatilewhile

对于这些关键字,大致可以分成以下这几种:

(1)数据类型关键字:char, double, float, int, long, short, signed, unsigned, void - 用于定义不同类型的变量或函数返回类型。

(2)控制流程关键字:break, continue, do, else, for, goto, if, return, switch, while - 用于控制程序的执行流程,实现条件判断、循环和跳转等功能。

(3)存储类关键字:auto, extern, register, static - 用于控制变量的存储方式和生命周期。

(4)修饰符关键字:const, inline, restrict, volatile - 用于修饰变量的性质、函数的行为或指针的限制。

(5)数据结构关键字:enum, struct, union - 用于定义枚举类型、结构体和共用体。

(6)其他关键字:case, default, sizeof, typedef - 用于在特定语法结构中使用,如switch语句、sizeof运算符和类型定义。

(7)扩展关键字:_Alignas, _Alignof, _Atomic, _Bool, _Complex, _Generic, _Imaginary, _Noreturn, _Static_assert, _Thread_local - C11标准中引入的扩展关键字,用于支持新的功能和语法。

一、数据类型关键字

C语言提供了多种数据类型关键字,用于定义不同类型的变量或函数返回类型。下面对每个数据类型关键字进行详细解释:

char:用于表示字符类型数据,占用一个字节(8位),可用于存储ASCII码中的字符或小整数。

double:用于表示双精度浮点数类型数据,占用8个字节(64位),可用于存储较大范围的浮点数。

float:用于表示单精度浮点数类型数据,占用4个字节(32位),可用于存储较小范围的浮点数。

int:用于表示整数类型数据,占用4个字节(32位),可用于存储整数值。

long:用于表示长整数类型数据,占用4个字节(32位)或8个字节(64位),可用于存储较大范围的整数值。

short:用于表示短整数类型数据,占用2个字节(16位),可用于存储较小范围的整数值。

signed:用于表示有符号整数类型,可与int、long、short等类型关键字组合使用,表示该类型的变量可以存储有符号整数。

unsigned:用于表示无符号整数类型,可与int、long、short等类型关键字组合使用,表示该类型的变量可以存储无符号整数。

void:用于表示空类型,表示函数没有返回值或指针没有指向具体的类型。

#include <stdio.h>

int main() {
    char c = 'A';
    printf("Character: %c\n", c);

    double d = 3.14159;
    printf("Double: %lf\n", d);

    float f = 2.71828;
    printf("Float: %f\n", f);

    int i = 42;
    printf("Integer: %d\n", i);

    long l = 999999999;
    printf("Long: %ld\n", l);

    short s = 32767;
    printf("Short: %hd\n", s);

    signed int si = -10;
    printf("Signed Integer: %d\n", si);

    unsigned int ui = 10;
    printf("Unsigned Integer: %u\n", ui);

    void *ptr = NULL;
    printf("Void Pointer: %p\n", ptr);

    return 0;
}

二、控制流程关键字

下面对每个控制流程关键字进行详细解释:

break:在循环语句(如for、while、do-while)或switch语句中使用,用于跳出当前循环或switch语句,终止循环或switch的执行。

continue:在循环语句中使用,用于跳过当前循环中continue之后的代码,进入下一次循环的迭代。

do:与while配合使用,构成do-while循环结构,先执行循环体中的代码,然后判断循环条件是否成立,如果成立则继续执行循环,否则结束循环。

else:与if配合使用,构成if-else条件语句,用于在条件不成立时执行的分支。

for:用于构建for循环结构,包括初始化表达式、循环条件和循环迭代部分,通过控制这些部分的执行顺序和条件,实现循环控制。

goto:用于无条件地将控制转移到程序的指定标签处,跳过中间的代码执行,通常不建议滥用goto语句,以免造成程序结构混乱。goto用的比较少,最好可以使用其他关键字代替goto的作用。

if:用于构建条件语句,根据条件的成立与否,选择不同的执行路径。

return:用于函数中,用于返回函数的返回值,并终止函数的执行。

switch:用于构建switch语句,根据表达式的值,选择不同的执行路径,可以用于替代多个if-else语句。

while:用于构建while循环结构,先判断循环条件是否成立,如果成立则执行循环体中的代码,然后再次判断条件,循环继续执行,直到条件不成立时结束循环。

三、存储类关键字(重点)

这里有4个关键字:auto、register、static和extern

1.auto关键字:生命周期仅存在于所在代码块,auto变量存于栈中

在C语言中,auto是默认的存储类关键字,当在函数内部声明变量时,如果没有使用任何存储类关键字修饰,默认为auto。auto关键字的主要作用是用于声明自动变量。

自动变量是在函数内部声明的局部变量,默认情况下,它的存储类为auto。自动变量的生命周期仅限于所在的代码块,当程序执行离开该代码块时,自动变量会被自动销毁。这意味着每次执行代码块时,自动变量都会重新初始化。

下面是一个使用auto关键字的示例:

#include <stdio.h>

void foo() {
    auto int num;  // 自动变量
    num = 10;
    printf("Value of num inside foo() is %d\n", num);
}

int main() {
    auto int num = 5;  // 自动变量
    printf("Value of num inside main() is %d\n", num);
    foo();  // 调用函数foo()
    printf("Value of num inside main() after calling foo() is %d\n", num);
    return 0;
}

在这个示例中,我们在main函数内部和foo函数内部都声明了一个auto型变量num。在main函数中,我们将num初始化为5,并打印其值。然后,我们调用foo函数,在foo函数中,我们将num初始化为10,并打印其值。在调用foo函数后,我们再次打印main函数内部的num值。

输出结果为:

Value of num inside main() is 5
Value of num inside foo() is 10
Value of num inside main() after calling foo() is 5

可以看到,num变量在不同的作用域中是独立的,它们的值互不影响。每次进入作用域时,自动变量都会重新初始化,并在离开作用域时被销毁

需要注意的是,在C语言中,auto关键字通常是可以省略的,因为它是默认的存储类。因此,上述示例中的auto关键字可以省略,代码仍然具有相同的行为。

2.register关键字:提示编译器将变量存入寄存器中提升运行效率

在C语言中,register是一种存储类关键字,用于声明寄存器变量。寄存器变量是建议编译器将其存储在寄存器中的变量,以提高访问速度。使用register关键字并不意味着变量一定会存储在寄存器中,它只是向编译器发出了一个建议。编译器可以选择忽略该建议,因为寄存器的数量是有限的,并且并非所有变量都适合存储在寄存器中

下面是一个使用register关键字的示例:

#include <stdio.h>

int main() {
    register int i;  // 声明寄存器变量
    int sum = 0;

    for (i = 1; i <= 10; i++) {
        sum += i;
    }

    printf("Sum of numbers from 1 to 10 is %d\n", sum);

    return 0;
}

在这个示例中,我们使用register关键字声明了一个寄存器变量i。然后,我们使用for循环计算从1到10的所有数字的总和。最后,我们打印总和的结果。

需要注意的是,register关键字在现代编译器中的使用已经不常见。现代编译器通常能够根据代码的优化策略自动选择合适的存储位置,包括寄存器、内存或缓存等。因此,使用register关键字并不能保证变量一定存储在寄存器中

此外,register关键字有一些限制和注意事项:
不能取寄存器变量的地址:由于寄存器变量存储在寄存器中,而不是内存中,所以不能使用&运算符获取寄存器变量的地址。
不能声明寄存器变量为全局变量:寄存器变量只能在局部作用域内声明,不能作为全局变量。
存储类限定符的优先级高于类型名:当使用存储类关键字和类型名一起声明变量时,存储类关键字的优先级更高。例如,register int* p;声明的是一个指向整型的寄存器变量指针。
尽管register关键字的使用已经不常见,但在某些特定的嵌入式系统或对性能要求非常高的场景中,仍然可以尝试使用register关键字来提高访问速度。

3.static关键字:改变变量和函数的作用域和生命周期,静态变量存于静态区 (重点)

这个改变变量和函数的作用域和生命周期怎么理解呢?
首先要明白什么叫作用域?什么叫生命周期?

(1)什么叫作用域?什么叫生命周期?

作用域(Scope)指的是一个变量或函数的可见范围,即在哪些地方可以访问到该变量或函数。作用域规定了变量或函数的可访问性,它决定了变量或函数在程序中的可用范围。

在C语言中,有以下几种作用域:
块作用域(Block Scope):变量在定义它的块(一对花括号之间)内可见,包括该块内的嵌套块。块作用域适用于在函数内部定义的变量。

函数作用域(Function Scope):变量在整个函数内可见,包括函数内的嵌套块。函数作用域适用于在函数外部定义的变量。

文件作用域(File Scope):变量在整个源文件内可见,即在文件的任何位置都可以访问。文件作用域适用于在函数外部定义的全局变量和函数。

生命周期(Lifespan)指的是一个变量或对象存在的时间范围,即变量或对象的创建和销毁的时间段。生命周期决定了变量或对象的可用时间。

在C语言中,变量的生命周期取决于其定义的位置和存储类别:
自动存储类别(Automatic Storage Class):自动变量的生命周期与其所在的块或函数的执行时间相同。当程序执行离开变量所在的块或函数时,自动变量会被销毁。

静态存储类别(Static Storage Class):静态变量的生命周期在程序的整个运行期间都存在,即使程序执行离开所在的块或函数,静态变量也不会被销毁。

动态存储类别(Dynamic Storage Class):动态变量的生命周期由程序员手动控制。动态变量使用malloc()函数或类似的函数进行动态分配内存,直到程序员显式释放内存时才会被销毁。

这里特别关注静态存储类别:静态变量的生命周期在程序的整个运行期间都存在,即使程序执行离开所在的块或函数,静态变量也不会被销毁。所以静态变量在整个程序运行中都不会被销毁,它始终存放在内存中的静态区域。而static起的就是这个作用,它可以修饰一个变量或者函数,使其成为静态。

(2)内存的四个分区

在这里插入图片描述

(3)static的作用:修饰局部变量、修饰全局变量、修饰函数

①修饰局部变量:改变局部变量的存储位置,把变量从栈区变到静态区,从而使得局部变量的生命周期变长。

其本质是:
普通的局部变量创建后是放在栈区中,这种局部变量进入作用域时创建,出了作用域就销毁;
但static修饰后的局部变量则放在静态区中,它改变了局部变量的存储位置,从而使得变量的生命周期延长,延长至程序结束才销毁。

②修饰全局变量:改变全局变量的链接属性,从而使得全局变量的作用域变小

全局变量的作用域十分的广,只要在一个源文件中定义后,这个程序中的所有源文件、对象以及函数都可以调用,生命周期更是贯穿整个程序。文件中的全局变量想要被另一个文件使用时就需要进行外部声明(以下用extern关键字进行声明)。
在这里插入图片描述
但是如果A文件定义了一个全局变量x,那么就不能在B文件中使用extern来读取x了,使得静态的全局变量x无法被其他文件调用。

其本质是:
全局变量本身是具有外部链接属性的,在A文件中定义的全局变量,在B文件中可以通过【链接】来使用
如果全局变量被static修饰,那这个外部链接属性就会被修改成内部链接属性,此时这个全局变量就只能在自己的源文件中使用

③修饰函数:与修饰全局变量十分相似,修饰函数时会改变函数的链接属性,从而使得函数的作用域变小

本身A文件中的函数,可以在B文件中用extern声明来使用。
但是当该函数被static静态化后,就不能被B文件调用了。

本质和全局变量很像:
函数本身也是有外部链接属性的;
被static修饰后,函数的外部链接属性被修改成内部链接属性,使得这个函数只能在自己的源文件内被使用,因此函数的作用域就变小了。

4.extern关键字:声明一个变量或者函数为全局作用域

在C语言中,extern是一个关键字,用于声明一个变量或函数是在其他源文件中定义的。它的作用是告诉编译器该变量或函数的定义在其他地方,不需要在当前源文件中定义。

具体来说,extern关键字的作用包括:

声明全局变量:当在一个源文件中使用extern关键字声明一个全局变量时,表示该全局变量是在其他源文件中定义的。这样可以在当前源文件中使用该全局变量而不需要重新定义它。

声明函数:当在一个源文件中使用extern关键字声明一个函数时,表示该函数是在其他源文件中定义的。这样可以在当前源文件中调用该函数而不需要重新定义它。

外部链接:extern关键字还指定了变量或函数的链接属性为外部链接。外部链接意味着该变量或函数可以在其他源文件中访问和使用。

需要注意的是,使用extern关键字声明的变量或函数,编译器不会为其分配内存或生成代码,它只是告诉编译器该变量或函数的定义在其他地方。因此,在使用extern关键字声明的变量或函数之前,需要确保其在其他源文件中有定义。

三、修饰符关键字:const, inline, restrict, volatile

1.const关键字:只读,无法修改,提升程序健壮性

在C语言中,const是一个关键字,用于声明一个常量。

const关键字的作用包括:
声明常量:使用const关键字可以将一个变量声明为常量,表示该变量的值在程序执行期间不可改变。常量在声明时必须同时进行初始化,且不能再次赋值。
类型安全性:通过将变量声明为常量,可以增加程序的类型安全性。如果试图修改const常量的值,编译器会报错。
优化编译器:编译器在处理const常量时,可以进行一些优化,例如将常量直接嵌入到生成的机器代码中,提高程序的执行效率。
防止意外修改:将变量声明为const常量可以防止在程序中意外修改其值,提高程序的可维护性和可读性。

常量可以用于各种数据类型,例如整型、浮点型、字符型等。声明常量的语法形式为:const 数据类型 常量名 = 值;

需要注意的是,const关键字只保证变量的值在程序执行期间不可改变,并不保证变量的地址不可改变。因此,const变量的地址是可以被修改的。
在这里插入图片描述
在这里插入图片描述
比如这里将函数的两个字符串参数用const修饰,那么就保护了其在这个test函数的作用域内是只读的,无法对齐进行修改。
但是在main函数中是可以对其进行修改的,说明const修饰的变量并不是变成了一个常量,而是单纯无法被修改。

那const修饰的变量存储在内存的哪个区域呢?

保存在只读数据区。只读数据区是一种特殊的内存区域,用于存储常量和只读的全局变量。它通常位于程序的静态存储区,其内容在程序执行期间保持不变

2.inline关键字:告诉编译器将函数的内容插入到这个函数被调用的地方,以避免函数调用的开销(内联函数)

在这里插入图片描述
这句话什么意思:比如test函数被主函数main调用时,函数调用会引入额外的开销,包括函数调用的准备和恢复、参数传递等,所以其实是有一些性能损耗的。用inline修饰函数后,该函数就变成了内联函数,相当于直接将函数代码插入到调用函数的地方,内联展开。
在这里插入图片描述
值得注意的是:使用了inline关键字,编译器也不一定保证函数一定被内联展开,它只是提供了一个建议。

那为什么所有的函数都不多多使用inline关键字来减少开销呢?
以下是一些原因:
函数体过大:如果函数体过大,将其内联会导致代码膨胀,增加程序的内存消耗。而且,内联函数的函数体会在每个调用点被复制,如果函数体过大,会导致代码重复的增加,可能会降低缓存命中率,从而影响程序的性能。
递归函数:递归函数无法进行内联,因为递归函数的调用点是在函数内部,而不是在函数外部。
调用频率低:如果一个函数的调用频率很低,将其内联可能得不偿失。因为内联函数的函数体会在每个调用点被复制,如果函数很少被调用,复制函数体的开销可能会超过函数调用的开销。
代码可读性:内联函数的函数体被复制到调用点,会增加代码的长度,可能会降低代码的可读性。如果函数的逻辑比较复杂,使用内联可能会使代码难以理解和维护。

3.restrict关键字:告诉编译器一个指针是独占的,没有别的指针指向相同的内存区域。

4.volatile关键字:确保本条指令不会因编译器的优化而省略,且要求每次直接从内存读值。

举一个例子:

int i = 10;
int main(void){
    int a, b;
    a = i;
    ...//伪代码,里面不含有对 a 、 b 以及 i的操作
    b = i;
    if(a == b){
        printf("a = b");
    }
    else {
        printf("a != b");
    }
    return 0;
}

如上代码,如果选择编译器优化,可能会被编译成如下代码(当然不是在C语言层面上优化,而是在汇编过程优化,只是使用C程序举例):

int i = 10;
int main(void){
    int a, b;
    a = i;
    ...//伪代码,里面不含有对 a 、 b 以及 i的操作
    b = i;
    printf("a = b");
    return 0;
}

因为在仅仅从main主函数来看,a == b是必然的,所以编译器就认为a≠b的操作不会发生,便优化掉了。

那么在什么情况,a 和 b不是必然相等呢?

  1. i 是其他子线程与主线程共享的全局变量,其他子线程有可能修改 i 值;
  2. i 是中断函数与主函数共享的全局变量,中断函数有可能修改 i 值;
  3. i 属于硬件寄存器,CPU可能通过硬件直接改变 i 的值(例如寄存器的标志位)

比如当执行a=i后,刚好发生一个中断导致i值改变,那么b=i这条语句后a≠b,如果之前被编译器优化了,那么就会导致无法正确执行相关程序,出现问题。

volatile的意思是“易变的”,用volatile修饰的变量表示这个变量的值随时有可能发生改变,因此提醒编译器编译时对该变量的存取操作不能进行优化,每次存取该变量都要从内存中存取,而不是使用其之前在寄存器中的备份。

要知道,以上面的程序为例,先是a=i,对这个i就要先从内存中读取,保存到寄存器里再赋给a,但是由于这个变量i很容易发生改变,所以如果不加volatile就可能导致内存里i变了但是寄存器保存的还是之前a=i的值,使得b=i读取时发生错误。所以必须加上volatile修饰i,如此即使i的值变化了编译器也能正确读取i的值。

那volatile关键字的应用场合有哪些?

volatile关键字的应用场合有以下几种:

1.多线程共享变量:当多个线程共享某个变量时,使用volatile关键字可以保证变量的可见性。即当一个线程修改了这个变量的值,其他线程能够立即看到最新的值,而不会使用缓存中的旧值。

2.中断:中断服务程序如果修改了其他程序中使用的变量,需要用volatile修饰该变量。

3.状态标志位:在多线程中使用volatile关键字可以保证状态标志位的可见性。例如,一个线程修改了某个标志位的值,其他线程可以立即看到最新的值,从而做出相应的处理。

4.硬件寄存器:比如状态寄存器,它的值有可能随着硬件的工作状态变化而改变,用volatile修饰。

那使用volatile关键字有什么优缺点吗?

四、数据结构关键字:enum, struct, union - 用于定义枚举类型、结构体和共用体。

1.enum关键字:定义一组相关的常量

enum是C语言中的关键字,用于定义枚举类型。

枚举类型是一种用户自定义的数据类型,用于定义一组具有相关性的常量值。枚举类型可以帮助提高代码的可读性和可维护性,使程序员能够更清晰地表示一组相关的常量。

使用enum关键字定义枚举类型的语法形式如下:

enum 枚举类型名 {
    枚举常量1,
    枚举常量2,
    ...
};

其中,枚举类型名是用户自定义的标识符,用于表示枚举类型。枚举常量是一组有序的常量值,用逗号分隔。枚举常量可以通过枚举类型名和常量名来引用。

例如,下面的代码定义了一个名为Color的枚举类型,包含三个枚举常量Red、Green和Blue:

enum Color {
    Red,
    Green,
    Blue
};

在程序中,可以使用枚举类型名和枚举常量名来表示枚举常量的值。例如,可以使用Color枚举类型名和Red枚举常量名来表示Red枚举常量的值:

enum Color c = Red;

枚举常量的值默认从0开始依次递增,也可以通过显式赋值来指定枚举常量的值。例如,可以在定义枚举常量时显式指定其值:

enum Weekday {
    Monday = 1,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
};

在这个例子中,Monday的值为1,后续的枚举常量依次递增。

总的来说,enum关键字用于定义枚举类型,在C语言中枚举类型是一种用户自定义的数据类型,用于定义一组相关的常量值。枚举类型可以提高代码的可读性和可维护性,使程序员能够更清晰地表示一组相关的常量。

2.struct关键字:定义多个不同类型的变量

struct是C语言中的关键字,用于定义结构体类型。

结构体是一种用户自定义的数据类型,可以用于组合多个不同类型的变量,形成一个新的数据类型。结构体可以包含多个成员变量,每个成员变量可以有不同的数据类型。

使用struct关键字定义结构体类型的语法形式如下:

struct 结构体类型名 {
    成员变量1;
    成员变量2;
    ...
};

其中,结构体类型名是用户自定义的标识符,用于表示结构体类型。成员变量是结构体中的变量,用于存储数据。成员变量可以是任意的数据类型,包括基本类型和其他结构体类型。

例如,下面的代码定义了一个名为Person的结构体类型,包含两个成员变量name和age:

struct Person {
    char name[20];
    int age;
};

在程序中,可以使用结构体类型名和成员变量名来表示结构体类型的变量。例如,可以定义一个Person类型的变量p,并为其成员变量赋值:

struct Person p;
strcpy(p.name, "Alice");
p.age = 25;

也可以在定义结构体类型的同时创建结构体变量,称为结构体的实例化。例如,可以直接定义一个Person类型的变量并初始化其成员变量:

struct Person {
    char name[20];
    int age;
} p = {"Bob", 30};

结构体变量的成员变量可以通过点操作符(.)来访问。例如,可以使用p.name和p.age来访问结构体变量p的成员变量。

总的来说,struct关键字用于定义结构体类型,在C语言中结构体是一种用户自定义的数据类型,用于组合多个不同类型的变量,形成一个新的数据类型。结构体可以包含多个成员变量,每个成员变量可以有不同的数据类型。结构体变量的成员变量可以通过点操作符来访问

3.union关键字:在同一存储空间内定义多个不同类型的变量

union是C语言中的关键字,用于定义联合类型。

联合(union)是一种特殊的数据类型,可以在同一内存空间中存储不同类型的数据。与结构体不同,联合中的成员变量共享同一段内存空间,只能同时存储其中一个成员的值。

使用union关键字定义联合类型的语法形式如下:

union 联合类型名 {
    成员变量1;
    成员变量2;
    ...
};

其中,联合类型名是用户自定义的标识符,用于表示联合类型。成员变量是联合中的变量,可以有不同的数据类型。

例如,下面的代码定义了一个名为Data的联合类型,包含两个成员变量i和f,分别表示整型和浮点型:

union Data {
    int i;
    float f;
};

在程序中,可以使用联合类型名和成员变量名来表示联合类型的变量。例如,可以定义一个Data类型的变量d,并为其成员变量赋值:

union Data d;
d.i = 10;
printf("%d\n", d.i);

d.f = 3.14;
printf("%f\n", d.f);

注意,联合变量的不同成员变量共享同一段内存空间,因此对一个成员变量的赋值会影响到其他成员变量。在上面的示例中,将d.i赋值后,d.f的值也会发生变化

可以使用sizeof运算符来获取联合变量所占用的内存大小。由于联合中的成员变量共享内存空间,所以联合的大小取决于最大的成员变量的大小

总的来说,union关键字用于定义联合类型,在C语言中联合是一种特殊的数据类型,可以在同一内存空间中存储不同类型的数据。联合中的成员变量共享同一段内存空间,只能同时存储其中一个成员的值。联合变量的大小取决于最大的成员变量的大小

五、其他关键字:case, default, sizeof, typedef - 用于在特定语法结构中使用,如switch语句、sizeof运算符和类型定义。

1.case关键字:特用于switch-case语句做分支判断

case关键字是在switch语句中用于指定不同的分支条件。它的语法如下:

switch (expression) {
    case value1:
        // 执行代码块1
        break;
    case value2:
        // 执行代码块2
        break;
    ...
    default:
        // 执行默认代码块
        break;
}

在switch语句中,expression是一个表达式,用于与每个case后面的值进行比较。如果expression的值与某个case后面的值相等,则执行对应的代码块。如果没有匹配的case值,则执行default代码块。break语句用于跳出switch语句,避免执行其他case分支。

case关键字的特点包括:

case值必须是常量表达式:case后面的值必须是常量表达式,即在编译时就可以确定的值,不能是变量或者运行时计算的表达式。

case分支顺序:switch语句中的case分支是按照出现的顺序进行匹配的。一旦匹配到一个case分支后,会执行该分支的代码块,并且会执行其后的所有分支代码块,除非遇到break语句或者switch语句结束。

default分支:default关键字用于指定默认的分支。如果没有任何case匹配成功,则会执行default代码块。default分支可以放在任意位置,但通常放在最后。

总之,case关键字是用于在switch语句中指定多个不同分支条件的关键字,用于根据不同的条件执行相应的代码块。

2.default关键字:switch-case语句无任何匹配情况再执行default代码

在C语言中,default关键字主要用于switch语句中的默认分支。与Java类似,default关键字在C语言中用于指定没有与任何case匹配的情况下执行的代码块。示例如下:

switch (expression) {
    case value1:
        // 执行代码块1
        break;
    case value2:
        // 执行代码块2
        break;
    ...
    default:
        // 执行默认代码块
        break;
}

当switch表达式的值与任何一个case值都不匹配时,程序会执行default代码块中的语句。default分支可以放在任意位置,但通常放在最后。

需要注意的是,C语言中的switch语句没有Java中的break语句自动跳出的机制。如果在某个case分支中没有使用break语句,程序会继续执行后续的case分支代码,直到遇到break或者switch语句结束。

总之,在C语言中,default关键字用于指定switch语句中的默认分支,用于处理没有与任何case匹配的情况。

3.sizeof关键字:计算对象的内存占用字节大小

sizeof关键字是C和C++语言中的一个运算符,用于计算对象或类型的大小。它返回一个无符号整数值,表示对象或类型在内存中所占用的字节数。
sizeof关键字的语法如下: sizeof(对象或类型)
其中,对象可以是变量、数组、指针等,类型可以是基本数据类型、结构体、联合体等。

使用sizeof关键字时,可以通过两种方式来计算大小:

计算对象的大小:
对于基本数据类型,sizeof返回该类型在内存中所占用的字节数。例如,sizeof(int)返回4,sizeof(char)返回1。
对于结构体和联合体,sizeof返回该结构体或联合体的所有成员所占用的总字节数。注意,sizeof不会计算填充字节。
对于指针,sizeof返回指针本身的大小,而不是指针指向的对象的大小

计算类型的大小:
使用sizeof关键字可以计算类型在内存中所占用的字节数。例如,sizeof(int)返回4,sizeof(struct MyStruct)返回结构体MyStruct在内存中的大小。

sizeof关键字在编程中有多种应用,例如:
动态分配内存时,可以使用sizeof来计算所需的内存大小。
在处理数据缓冲区时,可以使用sizeof来计算缓冲区的大小,以确保不会越界访问。
在编写通用代码时,可以使用sizeof来获取对象或类型的大小,以便进行后续的操作。
需要注意的是,sizeof关键字在编译时进行计算,而不是在运行时。因此,它不会对对象进行实际的访问或计算。此外,sizeof关键字返回的是无符号整数值,可以用来进行大小比较、位运算等操作。

4.typedef关键字:自定义新的数据类型

typedef关键字是C和C++语言中的一个关键字,用于定义类型别名。它可以为已有的数据类型或用户自定义的数据类型创建一个新的名称,以方便在代码中使用。

typedef关键字的语法如下: typedef 原类型名 新类型名;

其中,原类型名可以是任何已有的数据类型,包括基本数据类型(如int、char、float等)、结构体、联合体、枚举等。新类型名是用户自定义的类型别名。

通过typedef关键字,可以实现以下功能:

创建类型别名:使用typedef可以为已有的类型创建一个新的名称,使得代码更加易读和易于维护。例如,typedef int Integer; 将int类型定义为Integer类型,以后就可以使用Integer来代替int。
简化复杂类型声明:当声明复杂的数据类型时,使用typedef可以简化代码。例如,typedef int* IntPtr; 将int指针类型定义为IntPtr类型,以后可以直接使用IntPtr来声明指针变量,而不需要每次都写int*。
提高代码可移植性:通过使用typedef定义的类型别名,可以使代码更具可移植性。当需要在不同的平台或编译器上进行移植时,只需修改typedef定义的别名,而无需修改大量的代码。
typedef关键字的使用示例:

typedef int Integer; // 创建类型别名,将int类型定义为Integer类型
typedef int* IntPtr; // 创建类型别名,将int指针类型定义为IntPtr类型

Integer num = 10; // 使用Integer类型别名声明变量
IntPtr ptr = &num; // 使用IntPtr类型别名声明指针变量

typedef struct {
    int x;
    int y;
} Point; // 创建类型别名,将结构体定义为Point类型
Point p1 = {2, 3}; // 使用Point类型别名声明结构体变量

需要注意的是,typedef只是为已有的类型创建了一个新的名称,而不是创建了一个新的类型。因此,typedef定义的类型别名与原类型是完全等价的,在编译过程中会被替换为原类型。

六、C99规范新拓展关键字

C99规范引入了一些新的拓展关键字,这些关键字用于扩展C语言的功能和语法。以下是C99规范引入的一些新拓展关键字:

restrict:restrict关键字用于指定指针的限定,表示该指针是访问对象的唯一且最初的方式。它可以帮助编译器进行优化,提高代码的性能。

_Bool:_Bool关键字用于声明布尔类型的变量,可以存储true或false的值。它的取值范围是0和1。

inline:inline关键字用于声明内联函数,指示编译器将函数的代码插入到调用处,以减少函数调用的开销。

_Complex:_Complex关键字用于声明复数类型的变量,可以存储实部和虚部的值。它可以在数学和信号处理等领域中使用。

_Imaginary:_Imaginary关键字用于声明虚数类型的变量,可以存储虚部的值。它是_Complex关键字的一部分。

_Alignas:_Alignas关键字用于指定对齐方式,可以用于声明变量或结构体的对齐方式。

_Alignof:_Alignof关键字用于获取类型的对齐方式,返回对齐方式的大小。

_Static_assert:_Static_assert关键字用于在编译时进行静态断言,用于检查一些编译时的条件和约束。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1196626.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

牛客网刷题笔记131111 Python实现LRU+二叉树先中后序打印+SQL并列排序

从学校步入职场一年多&#xff0c;已经很久没刷过题了&#xff0c;为后续稍微做些提前的准备&#xff0c;还是重新开始刷刷题。 从未做过计划表&#xff0c;这回倒是做了个计划表&#xff0c;希望能坚持吧。 刷题比较随性且量级不大&#xff0c;今天就写了2个算法2个sql&#x…

第四节(2):修改WORD中表格数据的方案

《VBA信息获取与处理》教程(10178984)是我推出第六套教程&#xff0c;目前已经是第一版修订了。这套教程定位于最高级&#xff0c;是学完初级&#xff0c;中级后的教程。这部教程给大家讲解的内容有&#xff1a;跨应用程序信息获得、随机信息的利用、电子邮件的发送、VBA互联网…

Qt界面设计时使各控件依据窗口缩放进行自适应填充的方法——使用布局、Spacer等控件

Qt界面设计时使各控件依据窗口缩放进行自适应填充的方法—使用布局、Spacer等控件 Chapter1 Qt界面设计时使各控件依据窗口缩放进行自适应填充的方法—使用布局、Spacer等控件Chapter2 Qt Creator中布局器详解01. 概述02. 开发环境03. 布局器概述04. 布局属性设置05. 弹簧条属性…

简单版本管理服务编写

说明: 制作android应用内更新的时候&#xff0c;经常会用到版本检查&#xff0c;下载&#xff0c;安装&#xff0c;这时候需要写一个版本管理服务。 本文说明了自己编写版本服务的简单经过。 解决方案: 该软件实现如下功能&#xff1a; 创建后台接口&#xff1a;版本软件上传…

基于PHP的设云尘资讯网站设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

保姆级自定义GPTs教程,无需任何代码!

11月10日&#xff0c;OpenAI正式宣布向所有ChatGPT Plus用户开放GPTs功能&#xff0c;一个人人都能开发自定义ChatGPT助手的时代降临。 GPTs支持无代码、可视化点击操作&#xff0c;这意味着即便你没有任何编程经验&#xff0c;只要有数据、脑洞大开的想法&#xff0c;就能开发…

探索微信小程序框架的精华——高质量的优秀选择

目录 引言&#xff1a; 1. 框架性能 2. 开发者工具支持 3. 文档和社区支持 4. 扩展能力 5. 使用率和稳定性 结语&#xff1a; 引言&#xff1a; 微信小程序作为一种轻量级、高效便捷的应用形式&#xff0c;已经在移动应用领域占据了重要地位。而其中&#xff0c;选择一个…

PostMan授权认证使用

Authorization 对于很多应用&#xff0c;出于安全考虑我们的接口并不希望对外公开。这个时候就需要使用授权(Authorization)机制。 授权过程验证您是否具有访问服务器所需数据的权限。 当发送请求时&#xff0c;通常必须包含参数&#xff0c;以确保请求具有访问和返回所需数据…

C/C++数据结构之链表题目答案与解析

个人主页&#xff1a;点我进入主页 专栏分类&#xff1a;C语言初阶 C语言程序设计————KTV C语言小游戏 C语言进阶 C语言刷题 数据结构初阶 欢迎大家点赞&#xff0c;评论&#xff0c;收藏。 一起努力&#xff0c;一起奔赴大厂。 目录 1.前言 2.题目…

C++学习笔记(二):C++是如何运行的

C是如何运行的 include 预处理语句&#xff0c;在编译前就会被处理。 main函数 程序入口。 #include <iostream>int main() {std::cout << "Hello World!" << std::endl;std::cin.get();return 0; }Visual Studio 解决方案平台指的是编译的代码的…

从零开始开发抖音小程序:与餐饮团购的完美融合

本文将探讨如何从零开始开发一个创新的抖音小程序&#xff0c;以其独特的特性与餐饮团购进行完美融合。 一、什么是抖音小程序&#xff1f; 抖音小程序为开发者提供了在用户观看视频时进行无缝体验的机会。通过借助抖音的庞大用户基础&#xff0c;开发者可以将自己的创意呈现给…

python3GUI--QQ音乐By:PyQt5(附下载地址)

文章目录 一&#xff0e;前言二&#xff0e;展示0.播放页1.主界面1.精选2.有声电台3.排行4.歌手5.歌单 2.推荐3.视频1.视频2.分类3.视频分类 4.雷达5.我喜欢1.歌曲2.歌手 6.本地&下载7.最近播放8.歌单1.一般歌单2.自建歌单3.排行榜 9.其他1.搜索词推荐2.搜索结果 三&#x…

Vuex持久化插件

Vuex数据默认是存储在内存中的&#xff0c;当然我们也可以将它存储在Local Storage&#xff0c;也可以指定某些数据存储在Local Storage 这样我们就用到了Vuex持久化插件vuex-persistedstate 安装vuex-persistedstate插件 npm install vuex-persistedstate --save 案列&#x…

数据管理系统-week1-文件系统、数据库和数据库管理系统

文章目录 前言一、 文件系统文件系统的限制 二、 数据库系统三、 数据库管理系统参考文献 前言 一、 文件系统 对于更高级的数据处理应用程序来说&#xff0c;基于数据块的持久存储逻辑模型过于简单数据块序列被划分为称为文件的数据块的可变子序列&#xff0c;与文件相关的名…

【ATTCK】MITRE Caldera -引导规划器

一、Caldera 概念 在详细介绍新的引导式规划器之前&#xff0c;我们先回顾一下与 Caldera 相关的概念的一些定义。 能力是 Caldera 可以执行的最小原子动作。对手由一组能力组成。例如&#xff0c;旨在发现和泄露感兴趣的文件的对手可能具有发现文件、创建暂存目录、将发现的文…

养老院信息展示预约小程序的效果如何

老龄化速度加快及快节奏时代&#xff0c;银发群体的老年生活&#xff0c;儿女往往难以照顾&#xff0c;养老院成为不少家庭或个人的选择&#xff0c;靠谱机构往往能带给老人丰富多彩的生活。 而在高需求的同时&#xff0c;无论对需求者还是养老院本身都存在一定难题&#xff1…

【Mysql】next-key 锁范围

背景 Mysql RR场景下通过next-key 锁解决了幻读的问题&#xff0c;而幻读通常是由 insert 新增的数据导致。所以next-key锁最终通过锁机制防止了一定条件下的新增数据从而解决了幻读问题。 规律 next-key锁可以由以下几条规律总结出锁范围 next-key会对查询过程中访问到的对…

灵活用工仿boss直聘招聘系统劳务系统源码

灵活用工仿boss直聘招聘系统劳务系统 开发语言&#xff1a; 后台&#xff1a;phpmysql&#xff0c;fastadmin框架 前端&#xff1a;vue&#xff0c;Uniapp 功能介绍&#xff1a; 1.登录 账号密码登录&#xff0c;微信手机号授权登录 2.首页&#xff1a;定位功能&#xf…

前端和空字符串、零比较时请务必使用===

在前端开发中遇到一个问题&#xff0c;以下两条语句的结果都是true。 console.log(0 ""); console.log(false ""); 这就导致了editingId为0的时候&#xff0c;if分支并没有执行&#xff0c;而我的本意是当editingId不是空也不是空字符串的时候执行分支…