我正在使用RPN(反波兰表示法)编写一个用于arduino的小型计算器。因为我还想使代码在x86笔记本电脑上运行,并为计算器程序设置一些配置参数,所以我使用诸如input_str
,input_int
和output_str
之类的函数,因此可以实现对于我的笔记本电脑或arduino,它们是不同的。
现在在input_str
char *input_str(void) {
#if IS_IO_STDIO
char iobuf[IO_BUF_SIZE];
fgets(iobuf, IO_BUF_SIZE, stdin);
if (IS_DEBUG) { printf("1. iobuf: %s\n", iobuf); }
if (IS_DEBUG) { printf("2. iobuf ptr: %p\n", iobuf); }
return iobuf;
#elif IS_IO_SERIAL
// TODO: implement serial input str
#endif // IS_IO_STDIO
}
使用fgets
获取用户输入(以供将来计算),1. iobuf printout
正确打印出用户键入的字符串,2. iobuf ptr
正确打印出{{1 }}不等于0。
当我在ipo循环中使用char *
的返回值时:
input_str
int ipo_loop(int16_t *stack, int *sp) {
// TODO: implement real ipo loop
int is_exit = false;
char *iobuf;
while (!is_exit) {
iobuf = input_str();
if (IS_DEBUG) { printf("3. iobuf ptr: %p\n", iobuf); }
output_str(iobuf);
}
return 0;
}
突然显示3. iobuf ptr
现在指向0。
iobuf
为什么突然变成0?
从iobuf
到char[IO_BUF_SIZE]
是否存在类型转换问题?
答案 0 :(得分:4)
在下面的代码中
char *input_str(void) {
char iobuf[IO_BUF_SIZE];
fgets(iobuf, IO_BUF_SIZE, stdin);
/* some code */
return iobuf;
}
您将返回本地数组iobuf
的地方导致未定义行为。在iobuf
中声明的char数组input_str()
具有局部范围,当控件从该函数退出时,其范围结束。
例如,如果您可以使用-Wall
,-Wextra
等flags来编译代码,例如
gcc -Wall -Wextra -Werror -Wpedantic test.c
编译器可能会警告您
警告:与局部变量关联的堆栈存储器地址 'iobuf'返回了[-Wreturn-stack-address]
上面的编译器警告会告诉您有关该问题及其可读性的所有信息。
创建动态数组并返回它,而不是返回本地数组。对于例如
char *iobuf = malloc(IO_BUF_SIZE * sizeof(*iobuf));
/* @TODO if malloc was success i.e check return value of malloc */
之后,像下面一样使用fgets()
扫描数据。
fgets(iobuf, IO_BUF_SIZE, stdin);
然后检索动态数组
return iobuf;
在完成动态返回的数组后,调用API ipo_loop()
时,请不要忘记free
以避免内存泄漏。例如
iobuf = input_str();
/* processing with iobuf.. here iobuf is dynamically returned array */
free(iobuf);