__attribute__((weak)) 修饰的函数没有被覆盖

需求 定义了同名函数后,原来的 __attribute__((weak)) 修饰的函数并没有被覆盖 ? 解决 打开生成的 map 文件,经过搜索,只找到了原来的函数,并没有找到新定义的函数。 在头文件中增加了新定义函数的声明 int _write(int file, char *ptr, int len);, 重新编译后,打开 map 文件,就可以找到新定义的函数了。 所以这个问题还是因为没有在头文件中声明,导致 printf 再调用的时候,只找到了弱定义的 write. 参考 ARM 之十一__weak 和 attribute((weak)) 关键字的使用 弱符号_attribute_((weak))

2023-11-10 · 1 min · 31 words · RamLife

assert 宏用于单元测试

需求 在单元测试中,需要能够自动判断结果和预期是否相符,如果不符,就报错。 解决 可以直接参考 st 的 assert_param 宏,根据需要,自己改造下,增加了额外的自定义错误说明语句。 // assert #include <stdint.h> #ifdef USE_ASSERT #define ASSERT_FAIL(expr, msg) ((expr) ? (void)0U : assert_fail((char*) msg, (char*)__FILE__, __LINE__)) void assert_fail(char* msg, char* file, uint32_t line); #else #define ASSERT_FAIL(expr) ((void)0U) #endif /* USE_ASSERT */ #ifdef USE_ASSERT void assert_fail(char* msg, char* file, uint32_t line) { /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ //SEGGER_RTT_printf(0, "assert_failed: file %s on line %d", file, line); Log::printf(Log::kError, "assert_failed1: file %s on line %d\n", file, line); while(1); } #endif /* USE_ASSERT */ void CurrentAverageTest() { ASSERT_FAIL((1 == 1), "CurrentAverageTest, result 1 error"); } 只要在编译参数中,增加 USE_ASSERT, 开启,即可使用宏来自动判断结果是否相符。...

2023-06-21 · 1 min · 117 words · RamLife

嵌入式软件单元测试

需求 以前自己是在每个模块的下面简单写个测试函数,用于模块的功能测试,最新想学习下嵌入式的单元测试。 解决 先汇总一下资料,等有时间跑一个 demo 起来看看结果. https://blog.csdn.net/ibanezjem/article/details/104891204 https://blog.csdn.net/zhengyangliu123/article/details/79486383 https://mp.weixin.qq.com/s/foD7rxvCXudzbUF-Hp84VA https://www.eet-china.com/mp/a35487.html https://www.zhihu.com/question/19755217 https://www.cnblogs.com/pingwen/p/9206406.html https://zhuanlan.zhihu.com/p/67162814 https://zhuanlan.zhihu.com/p/67164631 https://zhuanlan.zhihu.com/p/67165611 https://zhuanlan.zhihu.com/p/67199540 https://blog.csdn.net/zhengnianli/article/details/104036227 https://blog.csdn.net/ybhuangfugui/article/details/131027470 https://blog.csdn.net/liao20081228/article/details/76984975 参考

2023-06-15 · 1 min · 20 words · RamLife

printf 打印指针类型

需求 在 32位 和 64位的平台上,指针类型占用的字节数不一样,使用 %d 直接打印指针对应的地址老是提示类型不对,有没有什么好方法呢? 解决 printf 其实专门有一个和指针类型对应的占位符,就是 %p. 参考 C学习:%p和%x、%lx、%hx、%llx区别辨析

2023-05-27 · 1 min · 13 words · RamLife

memcpy 和 memmove 区别

需求 正常我们直接复制内存使用的是 mcmcpy, 今天看到 memmove 感到比较奇怪,他们的区别是什么? 解决 相同点 memcpy 和 memmove 都是内存复制。当目的内存和源内存没有交集的情况下,随便使用哪个都可以。 不同点 当目的内存和源内存有交集的时候,因为 memcpy 是从前向后复制的,所以会造成部分内容出错。而 memmove 会先判断,如果有交集,那么就从后向前复制。 注意 现在有些系统,在实现的时候, memcpy 和 memmove 是等价的,所以可以直接用 memmove. 当效率要求不高的时候,可以统一使用 memmove, 当效率要求比较高的时候,在程序中无交集情况下,使用 memcpy, 有交集情况下使用 memmove. 参考 详解memcpy和memmove函数的使用

2023-05-25 · 1 min · 33 words · RamLife

结构体位域字节对齐

需求 有些时候,一些数据只占用几个 bit,而且是紧密排列的,所以就会考虑使用结构体位域,最好能再带上 union,使用起来会更加方便,但是位域是否字节对齐? 解决 经过测试,如果每一段的位域都在单个字节内,没有跨字节,那么就可以直接使用,字节是对齐的。否则每个跨字节的位域会多占用一个字节,会造成整体的数据错位。 参考 结构体(Struct)、联合体(Union)和位域 union联合体与内存对齐 C语言位域(位段)详解 UNION和位域的使用

2023-05-18 · 1 min · 11 words · RamLife

fwrite 返回值并不是字节数

需求 使用 fwrite 写入时,返回值和字节数目对应不上,这是什么情况? 解决 因为 fwrite 和 write 之类的系统直接提供的接口不一样, fwrite 返回的是写入的数据块的个数。如果数据是以字节作为数据来写入,那么返回值就是字节数,否则返回值是和 count 这个参数相关联,而不是单纯的字节数。 size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream); // -- buffer:指向数据块的指针 // -- size:每个数据的大小,单位为Byte(例如:sizeof(int)就是4) // -- count:数据个数 // -- stream:文件指针 参考 fwrite()的返回值随着格式的不同返回值也不同; fopen()、fwrite()、fread()函数使用说明与示例 C 库函数 - fwrite()

2023-04-10 · 1 min · 43 words · RamLife

printf 16进制大写输出,并且左补零

需求 在某些情况下,需要打印的数据,16进制表现形式,并且达到固定的位数,不足的左边补零。 解决 snprintf(tmp, sizeof(tmp), "%04X", ack.command); % 格式说明的起始符号 0 空位补0 m.n m指宽度,n指小数精度 X 16进制大写字符 参考 printf()如何进行“左补零”的操作 c语言printf()输出格式大全 C语言printf指定宽度的格式化输出 C语言中sprintf()函数的用法

2023-04-05 · 1 min · 20 words · RamLife

调试信息宏 FILE LINE FUNCTION

需求 调试时,希望打印信息能够包含文件名,行号,函数名等 解决 编译器有提供相应的宏,可以如下使用,注意,行号是数值。 printf("error in %s %d %s\n", __FILE__, __LINE__, __FUNCTION__); 除了这些以外,还有其他的一些可用的宏,比如说: __DATE__ : 当前系统日期 Apr 19 2019 __TIME__ : 当前系统时间 例如 15:39:58 __TIMESTAMP__ : 当前时间日期 例如: printf(_TIMESTAMP_); 打印结果 Fri Apr 19 16:24:31 2019 参考 C/C++中的_FUNCTION_,__FILE__和__LINE__ 系统常用宏定义__TIME__ DATE __LINE__等 C/C++ 宏定义 FILE__、_LINE_、_func_、__TIME 等

2023-03-06 · 1 min · 44 words · RamLife

连接字符串的宏

需求 需要宏来生成字符串,降低人工输入和防止出错 解决 可以使用 #, 让相应的参数作为字符串进行填充。 #define OUT(s) fprintf(stderr, "out: " #s "/n"); OUT(div == 0); // fprintf(stderr, "out: " "div == 0" "/n"); ## 可以用来连接多个参数,减少代码生成。用法简单: #define NAME(n) name##n int NAME(a); NAME(a) = 123; printf("%d\n", NAME(a)); 参考 C语言中如何使用宏连接多个字符串(#和##的用法) C++ 宏字符串拼接、宏参数拼接成符号、宏嵌套、宏变长参数 C语言宏定义##连接符和#符的使用

2023-03-06 · 1 min · 41 words · RamLife