【问题标题】:Usage of void pointers across different platforms跨平台使用 void 指针
【发布时间】:2015-01-01 07:43:10
【问题描述】:

我听说应该首先将指针转换为 void 以确保跨平台的值的一致性,并且应该使用 %p 格式说明符。为什么会这样?问题究竟是什么?

int x=100;
int *pi=&x;
printf("value of pi is: %p",(void*)pi);

【问题讨论】:

    标签: c pointers void-pointers format-specifiers


    【解决方案1】:

    printf 是一个可变参数函数,必须传递正确类型的参数。标准说%p 接受void *

    Implicit cast doesn't take placevariadic functions

    引用N1570 7.21.6.1 fprintf 函数

    p : 参数应该是一个指向 void 的指针。指针的值为 在实现定义中转换为打印字符序列 方式。

    【讨论】:

    • 请注意,您的引用肯定是 POSIX 特定的,IIRC 标准要求两个不同的指针具有不同的特定于实现的输出。
    • @MatteoItalia 谢谢。已更新。
    • 很好的引用,但在实践中,不发生隐式转换这一事实如何影响传递参数的值(换句话说,如何转换到void* 使pi 的值有什么不同)?
    • @barakmanos C 规范不要求 void *T *(其中 T 是非空类型)的大小相同。在指向void 的指针和指向(比如说)int 的指针的情况下,可变参数实现可能决定推送不同数量的字节。但是printf 会将此指针的值作为void * 类型获取,并将调用未定义的行为。
    【解决方案2】:

    不同指针类型的内部表示或大小不一定相同。

    例如在一个系统上,sizeof(void*) 可能是 2,但 sizeof(int*) 是 1。

    由于printf是可变参数函数,它不能检查传入参数的类型。如果您将int* 传递给它,它会读取错误的字节数,因为它需要void*

    【讨论】:

      【解决方案3】:

      printf 中的p 转换规范需要void * 类型的参数。 C 表示,如果您传递其他类型的参数,则调用会调用未定义的行为。

      除此之外,不同类型的指针对象不需要具有相同的表示形式:例如,C 不保证 sizeof (void *) == sizeof (int *)。 C 只保证void * 与指向字符类型的指针具有相同的表示。

      【讨论】:

      • 我不会说“除此之外”,而是说“那是因为”:如果不是#2,那么#1就没有理由。这意味着,如果所有指针在内存布局方面看起来彼此相似,则无需为非void * 指定 UB。
      • @glglgl 我仍然更喜欢“除此之外”,因为除了 C 说 指向其他类型的指针不需要具有相同的表示或对齐要求之外,还有一个特定的 C 规则对于 fprintf 函数,表示 p 的参数应为指针 void *
      • 你是对的,但两者之间的联系仍然存在。
      • 我很好奇……你能举一个系统或编译器的例子吗?sizeof(void*) != sizeof(T*)T 是什么)?
      猜你喜欢
      • 2021-09-13
      • 2014-05-30
      • 1970-01-01
      • 1970-01-01
      • 2013-12-18
      • 2019-05-24
      • 1970-01-01
      • 2018-03-28
      • 1970-01-01
      相关资源
      最近更新 更多