【嵌入式八股21】C语言基础知识
一、数据类型说明
在 C 语言中,不同的数据类型在不同平台下占用的字节数有所不同。以下是常见数据类型在 16 位、32 位和 64 位平台下的字节数情况:
char | 1 字节 | 1 字节 | 1 字节 |
pointer(指针) | 2 字节 | 4 字节 | 8 字节 |
short(短整型) | 2 字节 | 2 字节 | 2 字节 |
int(整型) | 2 字节 | 4 字节 | 4 字节 |
float(单精度浮点数) | 4 字节 | 4 字节 | 4 字节 |
double(双精度浮点数) | 8 字节 | 8 字节 | 8 字节 |
long(长整型) | 4 字节 | 4 字节 | 8 字节 |
long long(长整型) | 8 字节 | 8 字节 | 8 字节 |
二、volatile 关键字
volatile 关键字用于指出变量的值是随时可能发生变化的,因此在每次使用该变量时,编译器都会强制从变量的内存地址中重新读取数据,而不是使用保存在寄存器中的缓存值。其常见的应用场景如下:
- 并行设备的硬件寄存器:例如,与外部设备进行交互时,硬件寄存器中的值可能会在程序执行过程中由外部设备自行改变,此时需要将访问该寄存器的变量声明为 volatile,以确保每次读取到的都是最新值。
- 中断服务子程序中会访问到的非自动变量(Non-automatic variables):在中断服务程序中,可能会访问到一些全局变量或静态变量。由于中断的发生是随机的,这些变量的值可能会在主程序执行过程中被中断服务程序修改。为了保证在主程序中能正确处理这些变量,应将其声明为 volatile。此外,对于这类变量的访问,可以使用关键区保护,以避免在多线程或中断环境下出现数据竞争。
- 多线程应用中被几个任务共享的变量:在多线程环境下,多个线程可能同时访问和修改同一个变量。为了确保每个线程都能读取到变量的最新值,避免因编译器优化导致的缓存数据不一致问题,需要将共享变量声明为 volatile。另外,在对共享变量进行操作时,可以考虑关闭系统调度(在某些特定情况下),以保证操作的原子性。
三、指针相关概念
(一)函数指针
函数指针是指向函数的指针变量,其声明格式为:int (*fun)(int *a);
,表示 fun
是一个指针,它指向一个返回值为 int
类型,参数为 int *
类型的函数。
(二)函数指针数组
函数指针数组是一个数组,数组的每个元素都是一个函数指针。声明格式为:int (*fun[10])(int *data, int size);
,表示 fun
是一个包含 10 个元素的数组,每个元素都是一个指向函数的指针,这些函数的返回值为 int
类型,参数为 int *
和 int
类型。
使用示例:
int (*sort_fun[5])(int *data, int size) = {
quick_sort, /* 快速排序 */
insert_sort, /* 插入排序 */
bubble_sort, /* 冒泡排序 */
heap_sort, /* 堆排序 */
selection_sort /* 选择排序 */
};
// 或者
sort_fun[0] = quick_sort;
sort_fun[1] = insert_sort;
(三)指针数组
指针数组是一个数组,数组的元素都是指针。声明格式为:int *a[10];
,表示 a
是一个包含 10 个元素的数组,每个元素都是一个指向 int
类型的指针。
(四)数组指针
数组指针是指向数组的指针变量。声明格式为:int (*a)[10];
,这里 a
是一个指针,它指向一个包含 10 个 int
类型元素的一维数组。当进行 a + 1
操作时,a
会跨过 10 个 int
型数据的长度。
(五)指针的指针
指针的指针是指向指针的指针变量。声明格式为:int **a;
,表示 a
是一个指针,它指向的是一个 int *
类型的指针。
四、main 函数的返回值
在 C 语言中,main
函数的返回值用于向操作系统反馈程序的执行状态:
- 返回 0:表示程序正常退出,即程序在执行过程中没有遇到任何异常或错误情况,顺利完成了所有操作。
- 返回负数:表示程序异常退出,通常意味着程序在执行过程中遇到了某种错误,如内存分配失败、非法操作等。操作系统可以根据返回的负数来进一步分析程序出错的原因。
五、const 关键字
(一)const T
用于定义一个常量,在声明的同时必须进行初始化。一旦声明,该常量的值将不能被改变。
示例:
const int constInt = 10; // 正确,声明并初始化一个整型常量
constInt = 20; // 错误,常量值不可被改变
const int constInt3; // 错误,未被初始化
(二)const T*
表示指向常量的指针,该指针不能用于改变其所指向的对象的值。
示例:
const int i = 5;
const int i2 = 10;
const int* pInt = &i; // 正确,指向一个 const int 对象,即 i 的地址
//*pInt = 10; // 错误,不能改变其所指向的对象的值
pInt = &i2; // 正确,可以改变 pInt 指针本身的值,此时 pInt 指向的是 i2 的地址
const int* p2 = new int(8); // 正确,指向一个 new 出来的对象的地址
delete p2; // 正确
//int* pInt = &i; // 错误,i 是 const int 类型,类型不匹配,不能将 const int * 初始化为 int *
int nValue = 15;
const int * pConstInt = &nValue; // 正确,可以把 int * 赋给 const int *,但是 pConstInt 不能改变其所指向对象的值,即 nValue
*pConstInt = 40; // 错误,不能改变其所指向对象的值
(三)const int* 与 int* const 的区别
指针本身是一种对象,int* const
表示常量指针,即指针本身的值不可改变,声明时必须初始化。
示例:
int nValue = 10;
int* const p = &nValue;
int *const p2 = &nValue;
// const int* 指针指向的对象不可以改变,但指针本身的值可以改变;int* const 指针本身的值不可改变,但其指向的对象可以改变。
int nValue1 = 10;
int nValue2 = 20;
int* const constPoint = &nValue1;
//constPoint = & nValue2; // 错误,不能改变 constPoint 本身的值
*constPoint = 40; // 正确,可以改变 constPoint 所指向的对象,此时 nValue1 = 40
const int nConstValue1 = 5;
const int nConstValue2 = 15;
const int* pPoint = &nConstValue1;
//*pPoint = 55; // 错误,不能改变 pPoint 所指向对象的值
pPoint = &nConstValue2; // 正确,可以改变 pPoint 指针本身的值,此时 pPoint 绑定的是 nConstValue2 对象,即 pPoint 为 nConstValue2 的地址
(四)const int* const
表示一个指向常量对象的常量指针,即既不可以改变指针本身的值,也不可以改变指针指向的对象的值。
示例:
const int nConstValue1 = 5;
const int nConstValue2 = 15;
const int* const pPoint = &nConstValue1;
//*pPoint = 55; // 错误,不能改变 pPoint 所指向对象的值
//pPoint = &nConstValue2; // 错误,不能改变 pPoint 本身的值
(五)const 助记方法
- 把一个声明从右向左读:
char * const cp;
应读成cp is a const pointer to char
,即cp
是一个指向char
类型的常量指针;const char * p;
读成p is a pointer to const char
,即p
是一个指向const char
类型的指针;char const * p;
与const char * p
等价,因为在 C++ 中没有const*
的运算符,所以const
只能属于前面的类型。 - C++ 标准规定,const 关键字放在类型或变量名之前等价:
char * const cp
:定义一个指向字符的指针常数,即const
指针。const char* p
:定义一个指向字符常数的指针。char const* p
:等同于const char* p
。const char **
:是一个指向指针的指针,那个指针又指向一个字符串常量。char **
:也是一个指向指针的指针,那个指针又指向一个字符串变量。
六、浮点数存储方式
(一)float 类型
float
类型占用 4 个字节(32 bits),其存储结构如下:
符号位 | 1 bit | 表示浮点数的正负,0 表示正数,1 表示负数。 |
指数位 | 8 bits | 用于表示浮点数的指数部分,以确定数值的大小范围。 |
尾数部分 | 23 bits | 表示浮点数的有效数字部分。 |
(二)double 类型
double
类型占用 8 个字节(64 bits),其存储结构如下:
符号位 | 1 bit | 表示浮点数的正负,0 表示正数,1 表示负数。 |
指数位 | 11 bits | 用于表示浮点数的指数部分,相比 类型,能表示更 |
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
一些八股模拟拷打Point,万一有点用呢