首先:我知道printf以及许多的printf类的函数都返回格式化后的字符长度。但是前提条件: 1.不占用实际内存 2.不使用NULL指针。
原因是使用G2553,硬件的内存非常有限,希望做到最小的系统内存开销。
printf函数已经用在它处,不能再使用了。
sprintf和vsprintf会造成已经数组的浪费。
并且IAR编译器中,使用NULL指针会造成系统崩溃(编译器并没有处理好NULL地址)。 如:char len = sprintf(NULL, "Hello world! %f\r\n", 3.14);会导致系统崩溃。
想问一下大家,有没有合适的函数可以用最小系统开销, 计算出格式化字符的最终长度。
比如(“hello world %02d”, 5)得到的结果应该是"hello world 05",长度应为14。
kqian0327:
你好,
可以使用一个GPIO外加一个delay函数,模拟串口发送的波特率。
这样可以在不占太多的软件资源输出log日志。
user1866843:
回复 kqian0327:
哦,不是这个意思的。
后来我倒是找到一个方法:
使用C99 引入的 snprintf 函数,这样目标地址就可以是NULL,而不必担心影响系统安全。具体是:
unsigned char len = snprintf(NULL, 0, format, …);
这样就只是返回格式化之后的长度。
但是我又遇到了一个问题,是关于malloc函数的。出现了申请不到的问题。具体是自己做了一个类似于printf的函数:
int my_printf(const char *format, …) { char * p_buffer; va_list vl; va_start(vl, format); unsigned char len = vsnprintf((char *)NULL, 0, format, vl); p_buffer = (char *)malloc(len); if (p_buffer == NULL) return -1; vsprintf(p_buffer, format, vl); va_end(vl); // … 将P_buffer中的内容输出至某设备(阻塞) // … free(P_buffer); }
这个函数正是应用了前面提到的,先计算出格式化字符的长度,然后用malloc动态申请处相应长度的空间,将格式化的字符放在其中,然后从串口中一次将其输出。但是出现了问题:
主程序A(单行,完全正确): my_printf("12345678\r\n"); 主程序B(不断循环输出,完全正确): while(1) my_printf("12345678\r\n"); 主程序C(顺序执行,靠后面的申请不到空间,而且好像有规律。) my_printf("1234567\r\n");—-成功 my_printf("1234567\r\n");—-成功 my_printf("123456\r\n");—-成功 my_printf("12345\r\n");—-成功 my_printf("1234\r\n");—-成功 my_printf("12345\r\n");—-成功 my_printf("123456\r\n");—-成功 my_printf("1234567\r\n");—-失败 my_printf("12345678\r\n");—-失败 my_printf("123456789\r\n");—-失败 my_printf("12345678\r\n");—-失败 my_printf("1234567\r\n");—-失败 my_printf("123456\r\n");—-成功 my_printf("12345\r\n");—-成功 my_printf("1234\r\n");—-成功 my_printf("12345\r\n");—-成功 my_printf("123456\r\n");—-成功 my_printf("1234567\r\n");—-失败 my_printf("12345678\r\n");—-失败 my_printf("123456789\r\n");—-失败 不知道怎么回事。好像是第一次申请长度n,能够成功,后面就无法再申请到比n大的空间了。