栈帧寄存器相关的编译选项

1. 编译选项 -fomit-frame-pointer表示在函数调用时不需要存储堆栈帧指针。此选项可减小生成的代码镜像大小, 一般在启用-On优化后会自动打开,也有的平台是默认打开的。 -fno-omit-frame-pointer表示将堆栈帧指针存储在寄存器中,帧指针是用来指示当前函数的栈帧(stack frame)的指针,在调试时可以帮助跟踪函数调用的堆栈信息。 在 AArch32 架构中,堆栈帧指针存储在寄存器R11A32代码)或寄存器R7T32代码)中. 在AArch64架构中,堆栈帧指针存储在寄存器X29中。作为帧指针使用的寄存器不能用作通用寄存器,但如果使用 -fomit-frame-pointer选项编译,则可用作...

用memcmp比较结构体会有什么问题

1. 示例一 先看下如下代码,思考一下,结果是输出a == b还是a != b? 1#include <stdio.h> 2#include <string.h> 3 4struct test_type { 5 char name[10]; 6 int i; 7 long l; 8}; 9 10int main(void) 11{ 12 struct test_type a = { 13 "test", 1, 2 14 }; 15 struct test_type b; 16 17 b.i = a.i; 18 b.l = a.l; 19 strcpy(b.name, a.name); 20 21 if (0 ==...

U-Boot和Linux内核的CRC函数

测试的时候,发现内核驱动里用crc32_le计算出的值和u-boot里用crc32计算出的值不一样。 又用python的zlib.crc32和把内容写到文件用linuxcrc32命令计算,发现与u-bootcrc32函数计算结果一致。 对比u-boot和linux内核用的crc32table,两者是一致的,后来查看代码,发现u-boot的crc32有个与0xffffffffL进行异或的操作。 实际linux的crc32_le函数与u-boot的crc32_no_comp函数是一致的。 1uint32_t __efi_runtime crc32(uint32_t crc, const Bytef *p, uInt len) 2{ 3...

C语言编译断言

1. 简介 c++17标准引入了static_assert。 1static_assert(bool-constexpr, message ) /// since C++11 2static_assert(bool-constexpr) /// since C++17 gnu c编译器也实现了_Static_assert,见Static Assertions。 2. 自定义 在没有static_assert的c语言中,可以自己实现类似的功能,如下: 2.1. 方法一 1#ifndef STATIC_ASSERT 2#define STATIC_ASSERT(exp)...

多维数组作为函数参数

1. 方法一:传递数组 C语言对多维数组的存储是按照一维数组来处理的,数组的每个维度在内存中按顺序存储。所以将多维数组作为参数传递时,必须指定多维数组子维度的大小,否则函数无法得知每个子维度结束地址。 第一维的长度可以指定,也可以不指定。 1void func1(int a1[], int x); 2void func2(int a2[][4], int x, int y); 3void func3(int a3[][4][8], int x, int y, int z); 2. 方法二:数组指针 把参数声明为指向数组的指针,此方法还是需要指定数组的子维度大小,不然函数内部无法使用下标去访问数组。 1void func1(int...

数组a、&a、&a[0]、&a[0][0]的区别与联系

1. 测试结果 分别声明一个一维数组a1[8]和二维数组a2[4][8],查看各个表达式的类型、地址、与首地址的差值,以及内存地址内存储的int变量值。数组内变量的低8位记录数组的行号和列号,其中高4位为行,低4位为列。先看一下测试程序给出的结果。 一维数组 1int a1[8]; 2sizeof(a1): 32(0x20) var typeof(var) (void *)(var) offset *(int *)(var) a1 int * 0x7ffe2034d2d0 0x00 0x00 &a1 int (*)[8] 0x7ffe2034d2d0 0x00 0x00 &a1[0] int * 0x7ffe2034d2d0...

gcc宏定义中的连接符和可变参数

1. 连接符 1.1. 字符串转换# #用来把参数转换成字符串 1#define pr_var(var) printf(#var " is %d\n", var); 2 3int main(int argc, char **argv) 4{ 5 int a = 1, b = 2; 6 7 pr_var(a); 8 pr_var(b); 9 pr_var(a+b); 10} 1.2. 参数连接## 在宏中,##可以用于参数连接。 1#define regname(n) x ## n regname(8)会被展开成x8。 2. 可变参数 2.1. 可变参数__VA_ARGS__ __VA_ARGS__ 是一个可变参数的宏,这个可变参数...

编译器预定义宏

1. 查看gcc预定义宏 在Linux下可以输入如下命令: 1gcc -posix -E -dM - < /dev/null window下,命令稍有不同 1gcc -posix -E -dM - < nul 1.1. 常见宏 macro desc __FILE__ 文件名 __LINE__ 行号 __func__ 函数名,早期版本为__FUNCTION__ __DATE__ 编译日期 __TIME__ 编译时间 __linux__ 编译平台是linux时定义