printf和指针
可能重复:
正确的格式说明符打印指针(地址)?
使用printf
打印指针时,是否需要将指针转换为void *
? 换句话说,在代码中
#include int main() { int a; printf("address of a = %p\n", &a); }
这个论点应该是(void *) &a
吗? 当没有进行显式转换时, gcc
似乎没有给出任何警告。
是的,需要施放到void*
。
int a; printf("address of a = %p\n", &a);
&a
的类型为int*
; printf的"%p"
格式需要一个void*
类型的参数。 int*
参数未隐式转换为void*
,因为printf
的声明不提供除第一个(格式字符串)之外的参数的类型信息。 格式字符串后面的所有参数都应用了默认参数升级 ; 这些促销活动不会将int*
转换为void*
。
可能的结果是printf
看到一个真正属于int*
类型的参数,并将其解释为类型为void*
。 这是类型惩罚,而不是转换,它具有未定义的行为。 如果int*
和void*
恰好具有相同的表示,那么它可能会发生作用,但语言标准并不保证,即使是暗示。 我所描述的类型惩罚只是一种可能的行为; 该标准几乎没有说明会发生什么。
(如果对具有可见原型的非可变参数函数执行相同操作,因此编译器在调用时知道参数的类型为void*
,那么它将生成执行隐式int*
代码- void*
转换。这不是这种情况。)
这是C还是C ++的问题? 对于C ++,似乎根据5.2.2 [expr.call]第7段,没有任何隐式转换为void*
。 似乎C99的6.5.2.2第6段也没有暗示任何指针类型的明确推广。 这意味着需要显式转换为void*
,因为指针类型可以具有不同的大小(至少在C ++中):如果不同指针类型的布局不相同,则最终会出现未定义的行为。 有人可以指出在使用可变参数列表时保证指针以适当的大小传递的位置吗?
当然,作为一名C ++程序员,这不是一个大问题:只是不要使用具有可变数量参数的函数。 不过,这在C语言中不是一种可行的方法。
我认为可能有必要施展。 我们确定指针的大小总是一样的吗? 我确定我最近在stackoverflow上读到struct*
的大小(或者只是对齐?)可能与union*
。 这表明一个或两个可能与void*
的大小不同。
因此,即使转换中的值变化不大或根本没有变化,也可能需要强制转换以确保指针本身的大小正确。
在print
, %p
需要void*
因此您应该显式地转换它。 如果你不这样做,如果你很幸运,那么指针大小和指针表示可能会节省一天。 但是你应该明确地将它强制转换 – 其他任何东西都是技术上未定义的行为。