为何固定赋值的unsigned char能存结果,scanf输入的却不行?
问题场景
我有一段可正常运行的代码,为unsigned char类型变量赋予固定值:
#include <stdio.h> #include <stdlib.h> int main2() { unsigned char a,b; a=1,b=2; a=(a+b)/2; printf("\nAverage: %d\n%18d",a,sizeof(a)); return 0; }
但当我改用scanf读取变量值时,代码无法正常工作:
#include <stdio.h> #include <stdlib.h> int main() { unsigned char a,b; scanf(" %d", &a); scanf(" %d", &b); a=a, b=b, a=(a+b)/2; printf("\nAverage: %d\n%18d",a,sizeof(a)); return 0; }
问题在于计算结果无法正确存入unsigned char,且似乎scanf仅保留了最后输入的值。以下是我尝试修复的代码:
#include <stdio.h> #include <stdlib.h> int main() { unsigned char b; unsigned short int a; scanf(" %u", &a); scanf(" %u", &b); b=b;{ b=(a+b); unsigned short int a; scanf(" %u", &a);{ b=(a+b)/3; printf("\nAverage: %u",b); printf("\n sizeof: %d",sizeof(b)); } } return 0; }
请问为何第一段代码能将计算结果存入unsigned char,第二段却不行?scanf读取值时存在什么差异?
问题解析
第一段代码正常运行的原因
直接给unsigned char赋值1、2时,这些数值都在unsigned char的取值范围(0~255)内,赋值操作会自动将整数转换为unsigned char类型存储。计算(a+b)/2得到1,同样在取值范围内,所以能正常存入变量a。printf用%d输出时,unsigned char会被自动提升为int类型,因此显示结果正确。
第二段代码出错的核心原因:scanf格式符与变量类型不匹配
scanf的%d格式符要求对应的参数是**int*类型**,但你传入的是unsigned char*类型指针。由于unsigned char通常占1字节,而int通常占4字节(或2字节),scanf会尝试把输入的整数值按int的字节长度写入到unsigned char变量的内存空间中,这会直接越界覆盖相邻内存(比如变量b的内存区域),导致变量值被破坏——这就是你看到“仅保留最后输入的值”的根源。这种类型不匹配属于未定义行为,程序运行结果完全不可预测。
正确的修复方案
要读取unsigned char类型变量,需使用%hhu格式符(C99及以上标准支持),它专门对应unsigned char*类型:
#include <stdio.h> #include <stdlib.h> int main() { unsigned char a, b; // 使用%hhu读取unsigned char scanf(" %hhu", &a); scanf(" %hhu", &b); a = (a + b) / 2; // %hhu输出unsigned char,%zu输出size_t类型的sizeof结果 printf("\nAverage: %hhu\n%18zu", a, sizeof(a)); return 0; }
另外,sizeof的返回值是size_t类型,使用%zu格式符输出是标准做法,避免类型不匹配导致的输出错误。
你尝试的修复代码的问题
你后续的代码存在变量重定义(在代码块内重复定义unsigned short int a)、逻辑混乱的问题,而且读取b时用%u对应unsigned char*依然是类型不匹配,同样会触发内存越界,因此无法正常运行。
内容的提问来源于stack exchange,提问作者Luca Fiorentino Heredia

