博客主页:https://blog.csdn.net/wkd_007
博客内容:嵌入式开发、Linux、C语言、C++、数据结构、音视频
本文内容:介绍标准C语言的32个关键字
金句分享:有机会一定要试试,其实试错的成本并不高,而错过的成本很高
C语言有多少个关键字?各个关键字有什么作用?本文将详细介绍C语言的关键字,可能一篇文章写不完 ,将在后面文章继续完善。C语言的关键字有32个,我将它主要分成下面四个方面来介绍。
功能 | 关键字 |
---|---|
类型(10个) | char、short、int、long、float、double、void、struct、union、enum |
修饰类型(8个) | auto、static、extern、register、volatile、const、signed、unsigned |
结构语句(11个) | do、for、while、break、continue、goto、if、else、switch、case、default |
其他(11个) | typedef、return、sizeof |
在学习下面的基本数据类型前,先弄清楚定义和声明有什么区别?怎么区分呢?
下面这两句代码,哪个是声明,哪个是定义?
char c;
extern int i;
extern
修饰,如果定义在本文件,则加不加extern
都可以。可以参考下面代码加深理解:
//extern.c
int extern_val;
int get_extern_val()
{
return extern_val;
}
复制上面代码保存为extern.c;
// main.c
#include
extern int extern_val; // 声明,变量定义在其他文件(extern.c)
extern int get_extern_val();// 声明,函数定义在其他文件(extern.c)
extern int val; // 声明,变量定义在本文件
extern int get_val(); // 声明,函数定义在本文件
// 下面是不加extern的声明,声明可以多次 2023-09-30 16:39:16
int val; // 不加extern的声明,变量定义在本文件
int get_val(); // 不加extern的声明,变量定义在本文件
int main()
{
extern_val = 0;
get_extern_val();
val = 1;
get_val();
return 0;
}
int val=1;
int get_val()
{
return val;
}
复制上面代码保存为main.c;
在Ubuntu 18.04系统使用版本为7.5的gcc编译器,通过命令gcc main.c extern.c
可以正常编译上面代码。
在32个关键字中,C语言的基本数据类型就占用了6个了,这些基本数据类型主要用来定义变量或者作为函数的参数或返回值类型。各个类型占用了多少个字节的内存?printf打印时用什么字符打印?这些基础知识,本文不涉及。有一点,long
型在32位系统是4个字节 ,在64位系统是8个字节。
数据类型就像模子一样,以内存为材料,打造出具有不同字节的变量。
当你定义一个char
型变量时,就像用拥有一个字节的“模子”从内存咔出来一个字节大小的“饼”;
当你定义一个int
型变量时,就像用拥有四个字节的“模子”从内存咔出来四个字节大小的“饼”;
总之,当使用数据类型定义变量,本质上就是从内存中取出一块该类型大小的内存,并给这个内存定义一个唯一的名字。
命名最好采用英文单词或其组合,别使用拼音,可望文知意,便于记忆和阅读;
尽量避免名字中出现数字编号,如 Value1,Value2 等
对在多个文件之间共同使用的全局变量或函数要加范围限定符(建议使用模块名(缩写)作为范围限定符)。 (GUI_ , etc)
由多个词组成时,每个词的第一个字母大写,其余全部小写,比如:int CurrentVal;
,或用下划线隔开,如:int current_val;
。
程序中不得出现仅靠大小写区分的相似的标识符,如:int x, X;
所有宏定义、枚举常数、只读变量全用大写字母命名,用下划线分割单词:
const int MAX_LENGTH = 100;
、#define FILE_PATH “/usr/tmp”
定义变量的同时千万千万别忘了初始化
。定义变量时编译器并不一定清空了这块内存,它的值可能是无效的数据。
不同类型数据之间的运算要注意精度扩展问题,一般低精度数据将向高精度数据扩展
作用域前缀命名规则:
全局变量、函数(global):g
静态变量、函数(native):n
数据类型前缀命名规则:
数据类型 | 前缀命令 | 例子 |
---|---|---|
boolean 类型 |
b | boolean bVariable; |
char 类型 |
c | char cVariable; |
int 类型 |
i | int iVariable; |
short 类型 |
s | short sVariable; |
long 类型 |
l | long lVariable; |
unsigned 类型 |
u | unsigned int uiVariable; |
double 类型 |
d | double dVariable; |
float 类型 |
f | float fVariable; |
struct 关键字,会将一些相关联的数据打包成一个整体,方便使用。
程序开发过程中经常要传送的不是简单的字节流(char 型数组),而是多种数据组合起来的一个整体,其表现形式是一个结构体,如果将这样的数据放在char型数组中,再使用指针偏移去获取数据,会使编程变得很复杂,而使用struct关键字定义的结构体可以轻松解决这种问题。
另外,当函数参数超过4个时,使用起来容易出错,降低效率,可以使用结构体压缩形参。
结构体所占的内存大小是其成员所占内存之和。如果结构体里没有成员,它的大小会跟编译器有关,下面代码,在Ubuntu18.04 使用gcc编译器编译后,没有成员的结构体大小是0,使用g++编译器编译后,没有成员的结构体大小是1.
// main.c
#include
typedef struct stStudent
{
}stStu;
int main()
{
printf("%ld\n",sizeof(stStu));
return 0;
}
C99 中,结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员,但结构中的柔性数组成员前面必须至少一个其他成员。柔性数组成员允许结构中包含一个大小可变的数组。 sizeof
返回的这种结构大小不包括柔性数组的内存。柔性数组的定义可以参考下面代码,虽然定义了arr数组,但它并没有使结构体占用的内存增加,整个stStu
的大小还是4个字节:
typedef struct stStudent
{
int i;
int arr[]; // 没指定数组大小
}stStu;
或
typedef struct stStudent
{
int i;
int arr[0];// 指定数组大小为0
}stStu;
柔性数组的使用可以参考下面代码,定义结构体指针pStu
指向malloc分配的一块内存,然后就可以通过pStu->arr[n]
去访问数组元素,因为这块内存是malloc分配的,如果arr
后面的空间不够的话,就可以动态去调整,这就是被成为柔性数组或可变长数组的原因:
stStu *pStu = (stStu*)malloc(sizeof(stStu)+100*sizeof(int));
完整使用例子如下:
// flexible_arr.c 2023-10-06 21:06:04
#include
#include
typedef struct stStudent
{
int i;
int arr[];
}stStu;
int main()
{
stStu *pStu = (stStu*)malloc(sizeof(stStu)+100*sizeof(int));
printf("stStu=%ld pStu=%ld\n",sizeof(stStu),sizeof(*pStu));
int i=0;
for(i=0; i<10; i++)
{
pStu->arr[i] = i;
}
printf("arr:");
for(i=0; i<10; i++)
{
printf("%d,",pStu->arr[i]);
}
printf("\n");
return 0;
}
如果文章有帮助的话,点赞、收藏⭐,支持一波,谢谢