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
没有节省内存,而是多使用了三个字节的代码

当然,在这样一个简单的测试中,您并不关心使用了多少代码或数据内存——事实上,您可能永远不会进行优化构建,只进行调试构建

在一段更复杂的代码中,情况可能会发生变化。例如,如果您有一个char
vs.
int
的数组,那么该数组显然会为
int
值占用更多的内存,前提是它不是一个非常小的数组,最终会出现在寄存器中

即使对于最终出现在寄存器中的数据,较短的数据类型也可能有所帮助,因为它可以将更多的数据打包到寄存器中(例如,通过使用
bl
bh
寄存器来表示字节值),从而减少溢出到实际内存中的数据

但在查看生成代码的大小以及它如何使用内存之前,您真的不知道


在任何情况下,这对于问题中的代码来说都是毫无意义的,因为使用
char
unsigned char
作为
getchar()
的返回值是不正确的。但有趣的是,看看为不同的数据类型生成了什么样的代码已在您的系统上签名。只需使用
unsigned char c
getchar
返回
int
,这是有原因的。为什么不直接使用
intc
?@jean françois:
getchar
返回一个
int
我知道。但是unsigned char也可以工作(并且消耗更少的内存:)@Jean-franoisfabre
unsigned char
如果您对检测
EOF
“消耗更多内存”感兴趣,那么它就不起作用了?哦,糟了,还有3个字节?这几乎是这台机器内存的0.00000002%:-)根据编译器的不同,您可以获得8字节整数和0.00000004%的RAM。臃肿的程序就是这样开始的:)但你是对的。