c - C 中泛型数据类型值的十六进制表示

标签 c generics hex void-pointers

<分区>

我试图用 C 编写一个函数来打印出通用数据类型值的十六进制表示。我的第一次尝试失败了,第二次成功了,为什么?

  1. 第一次尝试

    #include <stdio.h>
    
    /* prints out the hexadecimal representation of a generic value */
    void show_hex(void*,size_t);
    
    int main() {
        int i = 12345;
        short s = 32767; /* 2^15 - 1 */
        show_hex(&i, sizeof(int));
        show_hex(&s, sizeof(short));
        return 0;
    }
    
    void show_hex(void *x, size_t sz){
         char *cx = x;
         int i;
         printf("0x");
         for (i = 0; i < sz; ++i)
             printf("%.2x", cx[i]);
         printf("\n");
    }
    

    输出:0x39300000 对于 int 情况,如小端计算机 (Mac OSX) 上预期的那样。对于 short 情况,它输出 0xffffffff7f 而不是 0xff7f

  2. 第二次尝试:

    typedef unsigned char *byte_pointer;
    
    int main() {
        int i = 12345;
        short s = 32767; /* 2^15 - 1 */
        show_hex((byte_pointer)&i, sizeof(int));
        show_hex((byte_pointer)&s, sizeof(short));
        return 0;
    }
    
    void show_hex(byte_pointer x, size_t sz){
        int i;
        printf("0x");
        for (i = 0; i < sz; ++i)
            printf("%.2x", x[i]);
        printf("\n");
    }
    

    对于这两种情况,此程序都按预期输出,int: 0x39300000短:0xff7f

最佳答案

对于第一种情况,改变:

printf("%.2x", cx[i]);

printf("%.2x", cx[i] & 0xFF);

普通的 char 类型是有符号的,因此 0xFF 被符号扩展为全 F 的 8 字节值,如打印输出所示。

第一个数字工作正常,因为所有字节都在 0x00..0x7F 范围内,因此该值没有转换为负整数——它保持正数。第二个数字没有计算出来,因为其中一个字节在 0x80..0xFF 范围内,因此被转换为负整数。 %.2x 将始终打印所有数字,但如果只有一个,则该数字前会有一个 0。 x 需要一个 unsigned int

对于 printf() 和其他可变参数函数,参数列表的 ... 部分中的参数默认提升,因此 char 类型(所有品种)被提升为 int(short),float 被提升为 double .

这记录在 C 标准 (ISO/IEC 9899-2011) 中:

6.5.2.2 Function calls

6 If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions.

7 If the expression that denotes the called function has a type that does include a prototype, the arguments are implicitly converted, as if by assignment, to the types of the corresponding parameters, taking the type of each parameter to be the unqualified version of its declared type. The ellipsis notation in a function prototype declarator causes argument type conversion to stop after the last declared parameter. The default argument promotions are performed on trailing arguments.

8 No other conversions are performed implicitly; in particular, the number and types of arguments are not compared with those of the parameters in a function definition that does not include a function prototype declarator.


半切向一边。

第 6 段的其余部分包括:

If the function is defined with a type that includes a prototype, and either the prototype ends with an ellipsis (, ...) or …, the behavior is undefined.

这句话必须在“如果表示被调用函数的表达式的类型不包含 原型(prototype),......'在段落的开头。这意味着,如果您调用一个用省略号 , ... 定义的函数,但调用时范围内没有原型(prototype),则行为未定义。每当调用可变参数函数时,都必须确保范围内有原型(prototype)。

关于c - C 中泛型数据类型值的十六进制表示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43246254/

相关文章:

c - 如果我在C中输入超过数据类型范围的数字会发生什么?

Java:将泛型类型传递给另一个泛型类型类

c# - 封闭式与开放式比较

python - 在 Python 中解析 128 字节十六进制 block 中的位

c - pthread 同步阻塞队列

c - 以不确定的顺序使用具有副作用的函数是否存在不确定的行为?

c - 如何使用 libcurl (或其他方式)从 HTTP 服务器检索文件?

c# - 服务契约中层次结构中的通用接口(interface)

将十进制转换为十六进制是截断第一位数字

hex - 如何在 Scratch 中快速从十六进制转换为十进制?