Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C中的printf()中将int类型转换为char_C_Casting - Fatal编程技术网

在C中的printf()中将int类型转换为char

在C中的printf()中将int类型转换为char,c,casting,C,Casting,结果:-48 所以我只是尝试一下,看看会发生什么,我得到了一个意想不到的结果 为什么是-48?它是怎么变成负数的?很简单:53200=0xCFD0和0xCF=207,对于有符号字符=48 语言律师视角: 我认为C99/C11标准中的正确参考是§6.3.1.3(重点是我的): 当整数类型的值转换为除_Bool以外的其他整数类型时,如果该值可以用新的 类型,它是不变的 否则,如果新类型是无符号的,则该值将通过重复地加上或减去一个大于该值的最大值来转换 可以在新类型中表示,直到值在 新型的 否则,新类

结果:-48

所以我只是尝试一下,看看会发生什么,我得到了一个意想不到的结果


为什么是-48?它是怎么变成负数的?

很简单:
53200=0xCFD0
0xCF
=207,对于
有符号字符
=48

语言律师视角: 我认为C99/C11标准中的正确参考是
§6.3.1.3
(重点是我的):

  • 当整数类型的值转换为除_Bool以外的其他整数类型时,如果该值可以用新的 类型,它是不变的
  • 否则,如果新类型是无符号的,则该值将通过重复地加上或减去一个大于该值的最大值来转换 可以在新类型中表示,直到值在 新型的
  • 否则,新类型是带符号的值不能在其中表示;结果是执行定义的或发出执行定义的信号
  • 请注意,
    char
    类型是有问题的,因为如果它实际表示为有符号或无符号,它也是实现定义的。标准本身完全定义的唯一方法是转换为
    无符号字符
    类型

    实际观点:
    假设对于您的实现
    sizeof(int)==4
    ,并且它使用2的补码方法存储有符号整数,则数字
    53200
    表示为:

    int *int_pointer = malloc(10);
    
    *int_pointer = 53200;
    
    printf("The integer at byte #0 is set to: %d \n", (char) *int_pointer);
    
    请注意,如果您只有很少的endian CPU(这可能是真实的假设),那么字节的顺序,或者更严格地说,它们在内存和CPU寄存器中的实际存储方式是颠倒的,即该数字存储为:

    0000 0000 0000 0000 1100 1111 1101 0000
    
    (无符号字符)53200
    产生的是(纯数学意义上的)减法as的结果(注意,标准保证
    sizeof(无符号字符)==1
    ):

    它是二进制的
    11010000

    可以从数学上证明,结果总是与“截止”相同,只保留最后一个最低有效字节作为强制转换的结果

    printf()
    的注释: 正如@pmg
    printf()
    所指出的,它是一个可变函数,由于默认的参数提升,它的可选参数类型
    无符号字符
    (或者
    有符号字符
    字符
    )总是被提升到
    int
    ,但这次它“只是一种形式”

    注:可供选择的双向运算符解决方案: 作为替代解决方案,您可以使用具有适当掩码的双向
    &
    和运算符来获取特定数字的最低有效字节,例如:

    53200 - 256 - 256 - ... - 256 = 53200 % 256 = 208
    

    将一个数据类型强制转换为另一个数据类型,该数据类型的宽度不足以容纳所有可能的值,这是一种未定义的行为。对于未定义的行为,编译器可以自由地做它想做的任何事情,因此通常它会做对实现者来说最省力的事情,因为他们自动正确,而你总是错误的


    因此,你不必问“为什么会这样?”——你应该庆幸没有得到52301或42,或者“救命!我被困在整数库中了!”

    我认为@fritzone是正确的。
    由于C中整数的范围是-32768到32767,因此在32767之后,它将变为-32768而不是32768,因此它将打印-48而不是53200。

    尝试值53201,它将打印出值-47,依此类推。

    @grzegorzzpetkowski可能它不是标准定义的,但事实就是如此。对于这个版本的运行,这个编译器在这个操作系统上使用这些选项编译,但仍然是。@Quentin:我已经发现它实际上是实现定义的,请参阅C99/C11 6.3.1.3。我很困惑。C中从int到char的转换是否总是截断该值,只保留低位8位?@HotLicks如果目标类型是有符号的,并且该值不适合,则不会进行转换。@HotLicks否,它是实现定义的。在您有经验的系统上,您可能已经习惯了这种行为,但是C已经在很多平台上使用过。接受可变数量参数的函数的
    部分中的参数根据需要进行转换。首先将
    int
    类型的值转换为
    char
    类型的值,然后将结果值隐式转换回
    int
    。我能说的是,您的实现将
    char
    视为有符号:)“假设对于您的实现
    sizeof(int)==32
    。”我想,您的意思是4;)@mafso:是的,是字节,不是位,更正了,谢谢你的发现:)增加了这个答案。int_指针最多可以容纳10个字节的数据。在int_指针中存储了4个字节的数据。char数据类型只能保存1字节的数据。因此,当您将4个字节强制转换为1个字节时,会出现溢出。这就是为什么您的数字返回为-48。要添加的是:编译器在这里所做的只是将值的低8位解释为有符号的数字。我认为这里没有UB,因为在C标准中,整数类型之间的转换是定义良好的(对于有符号的类型,它的实现定义)
    53200 - 256 - 256 - ... - 256 = 53200 % 256 = 208
    
    *int_number & 0xff   /* mask is 0000 0000 0000 0000 1111 1111 */