字母字符打印错误的ISO代码

时间:2018-02-10 21:08:44

标签: c

所以,我有这个简单的代码,

    #include <stdio.h>
    #include <stdlib.h>

    int main()
    {
        char c;
        c = getchar();
        printf("%d",c);
        return 0;
    }

现在让我们说c ='α' - 希腊字母表中的a。根据ISO8859-7,该程序应该打印225,但它打印-31。 有谁知道导致这个错误的原因是什么?

3 个答案:

答案 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会返回一个整数,它会溢出char225-256 = -31

只需使用unsigned char c;,或更简单地使用int,这会消耗更多内存(不应该是一个问题)但能够将EOF255区分开来。转到int:这很简单,没有人会对此感到疑惑。

答案 2 :(得分:0)

这不是问题的答案,但我想解决(双关语)intchar变量增加的内存使用量,如其他评论和答案,以及一些代码格式化将有助于此。

当你谈论记忆的使用时,最好的政策就是为惊喜做好准备。

如果存储在寄存器而不是存储器中,那么像问题中那样的局部变量通常会占用字节的内存而不管其大小。但是,可能需要更多的代码来转换数据宽度,就像这里的情况一样。

为了比较,这里是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不是保存内存,而是使用了三个字节的代码。

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

事情可能会在更复杂的代码中发生变化。例如,如果您有charint数组,那么显然该数组将为int值占用更多内存,假设它不是&#39 ; ta非常小的数组,最终在寄存器中。

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

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

在任何情况下,对于问题中的代码来说,这都是一个没有实际意义的问题,因为使用charunsigned char作为{{的返回值'是不正确的1}}。但是看看为不同的数据类型生成什么样的代码很有意思。