GCC中使用char/u8/s8变量出现值异常问题求助(附代码)
GCC下char/u8类型变量被意外清零问题的分析与解决
核心问题:scanf格式符与变量类型不匹配导致的未定义行为
你碰到的是C语言中典型的未定义行为——用%d格式符读取输入到u8/s8(本质是unsigned char/signed char)类型变量里。%d格式符要求传入int类型指针,但你传的是char类型指针,scanf会尝试向该位置写入int大小的数据,直接越界覆盖相邻内存。
你的全局变量NumberofElements和NumbertoSearchfor在内存中连续存放,所以读取NumbertoSearchfor时的越界操作直接把NumberofElements的内容冲成了0。Visual Studio表现“正常”只是巧合,它的内存布局刚好没让越界触发可见错误,但这依然是非法代码,随时可能出问题。
修复步骤
1. 替换为正确的scanf格式符
字符类型对应专门的格式符:
signed char(s8)用%hhdunsigned char(u8)用%hhu
把代码里所有scanf调用改成对应格式:
// 读取数组元素个数 printf("Please enter the number of elements for the array: "); scanf("%hhu", &NumberofElements); // 读取数组元素 void Scan_Array() { for (u8 i = 0; i < NumberofElements; i++) { scanf("%hhu", &array[i]); } } // 读取要查找的数字 printf("\nPlease enter the number you want to search for: "); scanf("%hhu", &NumbertoSearchfor);
2. 修正其他潜在问题
- main函数返回值:标准C规定
main必须返回int,把void main()改成int main(),并在函数末尾加return 0; - 递归调用main的内存泄漏:
continuity里递归调用main会导致之前malloc的数组内存无法释放,改成循环结构:
int main() { while (1) { u8 NumbertoSearchfor, NumberofElements, * array = NULL; printf("Please enter the number of elements for the array: "); scanf("%hhu", &NumberofElements); array = (u8*)malloc(NumberofElements * sizeof(u8)); printf("Please enter the values stored in the array:\n"); Scan_Array(array); Sort(array); printf("\nPlease enter the number you want to search for: "); scanf("%hhu", &NumbertoSearchfor); Binary_Search(array, NumbertoSearchfor, NumberofElements); free(array); // 每次循环结束释放内存 u8 cont = 0; printf("\nDo you want to continue? Y/N\n"); scanf(" %c", &cont); if ((cont == 'Y') || (cont == 'y')) { continue; } else if ((cont == 'N') || (cont == 'n')) { printf("Thanks for using our program. Exiting ..."); break; } else { printf("Invalid answer."); } } return 0; }
(注:这里把全局变量改成局部变量,更符合规范,同时修改Binary_Search等函数为接收参数的形式,避免依赖全局变量)
- Sort函数参数错误:原代码中
Sort()定义无参数,但调用时传了array,修正为void Sort(u8 *array),或者去掉调用时的参数(若依赖全局array)。
3. 为什么volatile/static等方法没用?
这些操作只是偶然改变了变量的内存布局或存储位置,让越界覆盖没影响到NumberofElements,但根本问题没解决,所以效果不稳定,完全依赖编译器行为,不是真正的修复。
总结
只要把scanf的格式符改成对应字符类型的正确格式,就能彻底解决变量被意外清零的问题。同时修正代码中的非标准写法,保证跨编译器的兼容性。
内容的提问来源于stack exchange,提问作者Mohamed Ahmed
相关产品推荐
相关产品推荐

