【嵌入式八股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,万一有点用呢

 浩鲸科技二面10人在聊
浩鲸科技二面10人在聊 投递大连飞创信息技术有限公司等公司10个岗位
投递大连飞创信息技术有限公司等公司10个岗位