C 语言中的标识符可以使用下划线、字母和数字组成,但也有一些词汇不能当作标识符,即关键字。经过多年的发展,C 语言到现在已经有了 40 多个关键字,如下图所示。
C 语言在 C90 版本,总共有 32
个标识符作为关键字,C99 增加了 5
个关键字,C11 又增加了 7
个关键字,这些关键字皆不能用于其他用途。根据关键字的作用可以将关键字进行分类,如用于表示数据类型的、用于流程控制的等等。
数据类型
C 语言有一些关键字用来表示数据类型,告知编译器声明的变量是存储整型还是字母等数据。
C语言中的数据类型都是通过上面的关键字来表示,如 int
表示缺省的整型类型,省略了 signed
修饰符,可表示的最小取值范围为 -32767~32767
,当使用 unsigned
修饰 int
时,就只能表示非负值了。
short
和 long
也是用于修饰 int
的关键字,修饰后所占用的存储空间会不同,如 short int
占用 2 字节,long int
占用 4 字节。
float
、double
用来声明浮点数,并且使用 long
修饰 double
后,可以存储比 double
更高的精度。
C99标准新增了三个关于数据类型的关键字, _Bool
类型表示布尔值,即 true
表示 1,, false
表示 0。_Complex
和 _Imaginary
分别表示复数和虚数。
除此之外,还有 struct
用于声明结构体,union
声明联合,enum
来声明枚举,void
在没有可用的值时使用,typedef
可以对上述数据类型声明类型别名,sizeof
用来计算类型或类型变量所占字节数大小。
存储类型
C语言通过存储类型来指定变量存储的内存类型、生命周期、和作用域。总共提供了 5 种关键字来表示,其中有一个是在C11标准中新增的。
auto
指定为变量,在块作用域内使用,但通常省略;当想要将变量存储到寄存器中时,可以使用 register
关键字来修饰;当想要变量在整个程序执行过程中一直存在,就使用 static
;extern
关键字用来指定外部变量,即在其他文件中定义,要在本文件中引用。C11又新增了 _Thread_local
关键字来修饰具有线程周期的线程局部变量,可将线程之间数据分开,避免对象在共享中被竞争。
限定类型
C语言中有四个关键字表示限定类型,C90标准加入的 const
与 volatile
,C99标准加入的 restrict
和 C11 标准加入的 _Atomic
。
const
在修饰指针时,共有三种情况,第一种情况写法是 const int *
或 int const *
。
int a = 10;
const int *p = &a;
*p = 20; // error: assignment of read-only location '*p'
*p = 20
会报错,这是因为 p
指向的值不能被改变,但可以通过 p
的引用来改变变量的值。
int a = 10;
const int *p = &a;
a = 20;
除了改变引用外,还可以改变指针本身的值。
int a = 10;
const int *p = &a;
int b = 20;
p = &b;
第二种写法是 float * const
,该写法的指针必须指向同一个地址,但所指向的值可以改变。
int a = 10;
int * const p = &a;
*p = 20;
第三种写法是 const int * const
,表明指针不能指向别处,所指向的值也不能更改。
int a = 10;
const int * const p;
int b = 20;
p = &b; // error: assignment of read-only variable 'p'
但还是可以通过改变 a
的值来改变。
int a = 10;
const int * const p;
a = 20;
流程控制
流程控制是决定程序运行的关键,其主要有顺序控制、分支控制和循环控制,通过 C 语言提供的关键字来控制,如下图所示。
实现循环结构可以使用 for
、while
和 do
三个关键字来实现,分支结构则使用 if
、else
和 switch
、case
和 default
来实现,并且在循环或分支中得到想要的结果后,想要从流程中跳转,就可以用上 break
、continue
、return
和 goto
了,当然,goto
最好少使用,它会让程序变得复杂,难以维护。
其它关键字
除以上介绍的关键字外,还有一些其他作用的关键字如下图所示。
函数调用过程包括建立调用、传递参数、跳转到函数代码并返回。使用宏定义使代码内联,可避免函数调用的开销,而 C99 标准提供的 inline
关键字可用来定义内联函数。
inline static int sum(int a, int b) { // 内联函数
return a + b;
}
int main() {
...
sum(10, 20); // 函数调用
...
return 0;
}
编译器可能会用 sum
中的代码替换函数调用,并可能会执行一些优化。
_Noreturn
修饰的函数不会将控制权交还给主调函数,以免滥用,并通知编译器可优化一些代码。
_Noreturn void failed() {
printf("failedn");
}
int main() {
printf("--start--n");
failed();
printf("--end--n");
return 0;
}
/*
--start--
failed
*/
C语言本身是不支持泛型编程的,但C11标准新增 _Generic
关键字实现一个泛型表达式来实现泛型编程。
_Generic(exp. type1:exp1, type2: exp2,···, default:expn)
_Generic
关键字括号中的第 1 项是表达式,后面每个项都由 type: exp
组成。type
用于匹配类型,exp
为匹配后的值。
#define TYPE(v) _Generic((v),
int:"int",
char: "char",
float: "float",
double: "double",
default: "other"
)
int main() {
int a = 5;
printf("%sn", TYPE(a)); // int
printf("%sn", TYPE(&a)); // other
return 0;
}
C11标准加入的 _Static_assert
关键字与断言 assert()
类似,但 assert()
是在运行时检查,而 _Static_assert
是在编译时检查,检查不通过,程序就无法通过编译。
int main() {
_Static_assert(sizeof(int) == 2, "16 bit is not supported");
return 0;
}
/*
error: static assertion failed: "16 bit is not supported"
*/

原文始发于微信公众号(海人为记):一文讲解C语言关键字
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/27417.html