【问题标题】:printf pointer argument type warning?printf指针参数类型警告?
【发布时间】:2013-04-25 21:19:12
【问题描述】:

有没有消除以下警告的好方法?我知道这是一个类型问题,因为我传递的是 unsigned long pointer 而不是 unsigned long,但 printf 是否以某种方式支持指针作为参数?我的书呆子想摆脱这个警告。如果没有,您如何处理使用printf 打印取消引用的指针值?

#include <stdio.h>

int main (void) {
    unsigned long *test = 1;
    printf("%lu\n", (unsigned long*)test);
    return 0;
}

警告:格式指定类型“无符号长”,但参数有类型

【问题讨论】:

    标签: c clang


    【解决方案1】:
    unsigned long *test = 1;
    

    不是有效的C。如果你想要一个指向1的对象的指针,你可以这样做:

    unsigned long a = 1;
    unsigned long *test = &a;
    

    或使用 C99 复合文字:

    unsigned long *test = &(unsigned long){1UL};
    

    现在也:

    printf("%lu\n", (unsigned long*)test);
    

    不正确。你实际上想要:

    printf("%lu\n", *test);
    

    打印unsigned long对象*test的值。

    要打印test 指针值(以实现定义的方式),您需要:

    printf("%p\n", (void *) test);
    

    【讨论】:

    • 这实际上会产生一个警告:一个不兼容的整数到指针转换初始化
    • @EhevuTov 来自unsigned long *test = 1;
    • %p 产生指针的地址。我想要实际的取消引用值应该是 1
    • @ouah 啊,我明白了。 %p 以 ascii 十六进制形式给出值。我越来越近了。
    • @EhevuTov 该标准以明确的方式定义了整数常量的类型,请参阅 C11 标准中的第 6.4.4.1 节。
    【解决方案2】:

    您并不真的需要对test 进行类型转换,%p 将采用任何指针(即使规范说它采用 void*)。使用%p 转换说明符是通过 printf 打印指针的最安全(令人惊奇的是,最便携)的机制。

    #include <stdio.h>
    
    int main (void) {
        unsigned long ul = 1;
        unsigned long *test = &ul;
        printf("%p\n", test);
        return 0;
    }
    

    编辑:哦,是的,还要小心尝试使用 intlong 等类型,具体取决于它们的类型大小。这是依赖于实现的,并且可以(并且确实)在不同的平台和这些平台的编译器上进行更改。 C 标准只是说long 必须至少与int 一样大。 POSIX standard for printf“长度修饰符”不以位为单位指定大小,而是按 C 类型指定大小。因此,您不能假设 sizeof(long) == sizeof(void*)(好吧,他们在 Linux 内核中做出了这样的假设,但它与 gcc 结合在一起,这始终是正确的)。

    【讨论】:

    • 这更多的是我得到的,但它返回的是地址,而不是值
    • 实际上,%p 需要一个 void*,并且传递一个不同的指针类型会调用未定义的行为。如果你向它传递一个实际上与void* 具有不同表示的指针,事情可能真的会崩溃。
    • 好吧,从技术上讲,规范说的是指向 void 的指针,但是如果您了解可变参数的实现方式,那就没关系了。但是,我想这确实进入了(编译器的)实现定义的领域。这就是为什么 gcc 不会为它发出警告的原因,因为它无法判断它是什么类型的指针,只是它是一个指针。不过,我会更新我的答案以反映这一点。但就看到奇怪的结果而言,我很想知道实际发生这种情况的实例(平台、编译器等)。
    • @EhevuTov,笨蛋,我以为你想要地址! :) 是的,只需在它前面加上一个星号即可取消引用它。
    • 这不是我的意思:如果我们有一个标准的方法来做我们必须做的事情,为什么我们要调用未定义的行为?添加强制转换来打印对象指针并不是什么大问题,只需键入几个字符即可;关于函数指针...我认为必须 print 它们并不常见(尽管也有一种标准方法可以做到这一点)。无论如何,我不知道它不起作用的任何上下文,我和你一样好奇知道这样的上下文。 P.S.:回答时不要忘记标记人:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-10
    • 2020-07-29
    • 2021-06-29
    • 2015-10-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多