所以,我有这个简单的代码,
#include <stdio.h>
#include <stdlib.h>
int main()
{
char c;
c = getchar();
printf("%d",c);
return 0;
}
现在让我们说c ='α' - 希腊字母表中的a。根据ISO8859-7,该程序应该打印225,但它打印-31。 有谁知道导致这个错误的原因是什么?
答案 0 :(得分:2)
getchar()
和朋友在int
范围或unsigned char
中返回EOF
值。 EOF
是负值。 @melpomene
使用int
。
int main() {
// char c;
int c;
c = getchar();
printf("%d\n",c);
return 0;
}
有人知道导致这个错误的原因吗?
getchar()
返回的值为225,但代码已分配给char
,在OP的平台上已签名,范围为-128到127.此调用实现定义的行为。
否则,新类型已签名且值无法在其中表示;结果是实现定义的,或者引发实现定义的信号。 C11dr§6.3.1.33
常见的实现定义的行为是将值减少256到-31
。其他结果也是可能的。
答案 1 :(得分:1)
因为您的系统已签署char c;
。
getchar
会返回一个整数,它会溢出char
:225-256 = -31
只需使用unsigned char c;
,或更简单地使用int
,这会消耗更多内存(不应该是一个问题)但能够将EOF
与255
区分开来。转到int
:这很简单,没有人会对此感到疑惑。
答案 2 :(得分:0)
这不是问题的答案,但我想解决(双关语)int
与char
变量增加的内存使用量,如其他评论和答案,以及一些代码格式化将有助于此。
当你谈论记忆的使用时,最好的政策就是为惊喜做好准备。
如果存储在寄存器而不是存储器中,那么像问题中那样的局部变量通常会占用零字节的内存而不管其大小。但是,可能需要更多的代码来转换数据宽度,就像这里的情况一样。
为了比较,这里是VS8617在x86发布模式下的编译代码,首先是int
变量:
int c;
c = getchar();
FF 15 B0 20 40 00 call dword ptr [__imp__getchar (04020B0h)]
printf("%d",c);
50 push eax
68 F8 20 40 00 push offset string "%d" (04020F8h)
E8 1F 00 00 00 call printf (0401030h)
83 C4 08 add esp,8
使用char
:
char c;
c = getchar();
FF 15 B0 20 40 00 call dword ptr [__imp__getchar (04020B0h)]
printf("%d",c);
0F BE C0 movsx eax,al ;; Widen 'char' to 'int'
50 push eax
68 F8 20 40 00 push offset string "%d" (04020F8h)
E8 1C 00 00 00 call printf (0401030h)
83 C4 08 add esp,8
生成的代码是相同的,除了char
版本有一个额外的三字节指令,movsx eax, al
在推送它之前将char
加宽到int
。因此,char
不是保存内存,而是使用了三个字节的代码。
当然,在这样一个简单的测试中,你并不关心使用了多少代码或数据内存 - 事实上,你可能根本不会进行优化构建,只需要进行调试构建。
事情可能会在更复杂的代码中发生变化。例如,如果您有char
与int
的数组,那么显然该数组将为int
值占用更多内存,假设它不是&#39 ; ta非常小的数组,最终在寄存器中。
即使对于最终寄存在寄存器中的数据,较短的数据类型也可能有所帮助,因为它可以将更多数据打包到寄存器中(例如,通过使用bl
和bh
寄存器等字节来实现值),所以较少的数据溢出到实际的内存中。
但在查看生成的代码的大小及其如何使用内存之前,您真的不知道。
在任何情况下,对于问题中的代码来说,这都是一个没有实际意义的问题,因为使用char
或unsigned char
作为{{的返回值'是不正确的1}}。但是看看为不同的数据类型生成什么样的代码很有意思。