Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.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和指针_C++_C - Fatal编程技术网

C++ printf和指针

C++ printf和指针,c++,c,C++,C,可能重复: 使用printf打印指针时,是否需要将指针强制转换为void*?换句话说,在类似于 #include <stdio.h> int main() { int a; printf("address of a = %p\n", &a); } #包括 int main(){ INTA; printf(“a=%p\n”的地址,&a); } 参数真的应该是(void*)&agcc在没有进行显式转换时似乎不会给出任何警告。我认为可能有必要进行转换。我们确定

可能重复:

使用
printf
打印指针时,是否需要将指针强制转换为
void*
?换句话说,在类似于

#include <stdio.h>
int main() {
    int a;
    printf("address of a = %p\n", &a);
}
#包括
int main(){
INTA;
printf(“a=%p\n”的地址,&a);
}
参数真的应该是
(void*)&a
<代码>gcc在没有进行显式转换时似乎不会给出任何警告。

我认为可能有必要进行转换。我们确定指针的大小总是相同的吗?我确信我最近在stackoverflow上读到,
struct*
的大小(或者可能只是对齐?)可能与
union*
的大小不同。这意味着其中一个或两个可以与
void*
的大小不同

因此,即使值在转换过程中变化不大,或者根本没有变化,也可能需要强制转换来确保指针本身的大小是正确的


print
中,
%p
需要一个
void*
,因此您应该显式地强制转换它。如果您不这样做,并且如果您幸运的话,那么指针大小和指针表示可能会节省时间。但是你应该明确地把它确定为——任何其他都是技术上未定义的行为。< /P> < P>这是C还是C++问题?对于C++,根据5.2.2[ExpReleCule]第7段,似乎没有任何隐式转换为<代码> VUL*。C99的6.5.2.2第6段似乎也不意味着指针类型的任何显式提升。这意味着需要显式转换为
void*
,因为指针类型可以具有不同的大小(至少在C++中是这样):如果不同指针类型的布局不相同,则最终会出现未定义的行为。有人能指出,在使用变量参数列表时,在哪里可以保证以适当的大小传递指针


当然,作为C++程序员,这不是一个很大的问题:只是不要使用具有可变数量的参数的函数。但是,在C语言中,这不是一种可行的方法。

是的,需要转换为
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语言中,您必须强制转换为
void*
(我对C++一无所知)。阅读7.19.6.1中的“p--参数应该是指向void的指针”。@MrLister:不,这是错误的。您必须为
printf
强制转换的原因是它是一个可变函数。原型无法告诉编译器每个参数所需的类型,因此隐式转换为
void*
对您没有帮助。你真的需要演员阵容。@SethCarnegie:我认为“宗教”这个词有误导性。如果您不强制转换为
void*
,在实际系统中,它将失败。@SethCarnegie:我没有一个具体的例子。我曾在
void*
int*
具有不同表示的系统上工作过(Cray T90,本机地址指向64位字,
void*
char*
在指针的高阶3位中存储字节偏移量,所有这些在软件中处理缓慢),但即使在该系统上,有效的
int*
指针也是指向同一地址的有效
void*
指针。但我相信也有类似的系统,字节偏移量不存储在指针本身中,
void*
int*
大@Keith:我认为问题不在于未来指针大小不同的系统。谢天谢地,这种落后已经过去了。现在的问题是优化。为了执行积极的优化,允许编译器假定您的程序只执行具有明确定义结果的操作。这可能会导致优化,导致具有未定义行为的程序(即使从天真的角度来看,未定义的行为似乎无害)严重崩溃。您的答案解决了实现中可能发生故障的机制,但关键的一点是,接口联系人要求您将正确的类型传递给
printf
,如果不遵循此要求,将导致UB。@H2CO3,我不会在这个问题上的任何地方进行向下投票。至少还有一个人提出了其他的理论,也许还有很多其他人在埋伏并投反对票。我没有投反对票,但我可以看到“我不确定,但可能是这样…”这样的回答怎么会被其他人认为值得投反对票。无论如何,遗憾的是,这是迄今为止最好的答案,也是唯一一个没有完全错误的答案。@R:希望这个问题以重复的形式结束;另一个问题