C 字母字符打印错误的ISO代码
我有一个简单的代码C 字母字符打印错误的ISO代码,c,C,我有一个简单的代码 #include <stdio.h> #include <stdlib.h> int main() { char c; c = getchar(); printf("%d",c); return 0; } #包括 #包括 int main() { 字符c; c=getchar(); printf(“%d”,c); 返回0; } 现在让我们假设希
#include <stdio.h>
#include <stdlib.h>
int main()
{
char c;
c = getchar();
printf("%d",c);
return 0;
}
#包括
#包括
int main()
{
字符c;
c=getchar();
printf(“%d”,c);
返回0;
}
现在让我们假设希腊字母中的c=‘α’-a。根据ISO8859-7,程序应该打印225,但它会打印-31。
有人知道这个错误的原因吗?因为
charc代码>已在您的系统上签名
getchar
返回一个整数,该整数溢出char
:225-256=-31
只需使用无符号字符c代码>相反,或者更简单地说是int
,它会消耗稍多的内存(不应该是问题),但能够区分EOF
和255
。选择int
:它很简单,没有人会对此感到奇怪。getchar()
和朋友返回一个int
,其值在unsigned char
范围内或EOF
中<代码>EOF
为负值
使用int
int main() {
// char c;
int c;
c = getchar();
printf("%d\n",c);
return 0;
}
有人知道是什么导致了这个错误吗
getchar()
返回了一个225的值,但是code将该值分配给了一个char
,它在OP的平台上以-128到127的范围签名。这将调用实现定义的行为
否则,新类型已签名,且无法在其中表示值;要么结果是实现定义的,要么引发实现定义的信号。C11dr§6.3.1.3 3
一种常见的实现定义行为是将值减少256到-31
。其他结果也是可能的。这不是问题的答案,但我想解决(双关语)一个int
变量与char
变量的内存使用增加的问题,正如在其他注释和答案中所讨论的,一些代码格式将对此有所帮助
当你谈论内存使用时,最好的策略是为惊喜做好准备
如果本地变量存储在寄存器而不是内存中,那么像问题中的一个本地变量通常会占用零字节内存,而不管其大小。但是,转换数据宽度可能需要更多的代码,这里就是这样
为了进行比较,这里是在x86发布模式下从VS2017编译的代码,首先是一个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 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
没有节省内存,而是多使用了三个字节的代码
当然,在这样一个简单的测试中,您并不关心使用了多少代码或数据内存——事实上,您可能永远不会进行优化构建,只进行调试构建
在一段更复杂的代码中,情况可能会发生变化。例如,如果您有一个charvs.int
的数组,那么该数组显然会为int
值占用更多的内存,前提是它不是一个非常小的数组,最终会出现在寄存器中
即使对于最终出现在寄存器中的数据,较短的数据类型也可能有所帮助,因为它可以将更多的数据打包到寄存器中(例如,通过使用bl
和bh
寄存器来表示字节值),从而减少溢出到实际内存中的数据
但在查看生成代码的大小以及它如何使用内存之前,您真的不知道
在任何情况下,这对于问题中的代码来说都是毫无意义的,因为使用char
或unsigned char
作为getchar()
的返回值是不正确的。但有趣的是,看看为不同的数据类型生成了什么样的代码代码>已在您的系统上签名。只需使用unsigned char c
getchar
返回int
,这是有原因的。为什么不直接使用intc
?@jean françois:getchar
返回一个int
我知道。但是unsigned char也可以工作(并且消耗更少的内存:)@Jean-franoisfabreunsigned char
如果您对检测EOF
“消耗更多内存”感兴趣,那么它就不起作用了?哦,糟了,还有3个字节?这几乎是这台机器内存的0.00000002%:-)根据编译器的不同,您可以获得8字节整数和0.00000004%的RAM。臃肿的程序就是这样开始的:)但你是对的。