以下C代码的输出是否因平台而异?

以下C代码的输出是否因平台而异?,c,printf,C,Printf,下面是C代码。我知道代码会导致内核转储。我们能看到的输出是什么?不同的平台有什么不同吗 #include <stdio.h> int main(){ printf("abc\n123"); printf("IHJ"); printf("%d", int* 0); return 0; } 我知道代码会导致内核转储 很遗憾,你的信息是错误的。上面的代码将不会编译。继续读下去 第三个printf在代码中存在问题 无效,它将不会编译。%d需要一个int变量

下面是C代码。我知道代码会导致内核转储。我们能看到的输出是什么?不同的平台有什么不同吗

#include <stdio.h>

int main(){
    printf("abc\n123");
    printf("IHJ");
    printf("%d", int* 0);
    return 0;
}
我知道代码会导致内核转储

很遗憾,你的信息是错误的。上面的代码将不会编译。继续读下去

第三个printf在代码中存在问题

无效,它将不会编译。%d需要一个int变量,而不是int键单词本身

即使,这个int*意味着一个演员阵容,比如

这也是错误的。您需要%p才能打印指针地址。为特定格式说明符提供无效类型的参数将调用

FWIW,当您面对UB时,您可能会遇到分段错误和核心转储

否则,只要为printf提供的格式说明符提供所需的类型和数量的参数,就可以有一个定义良好的行为

要学究气,int main应该是int mainvoid

这将无法编译。如果你是说

printf("%d", (int*)0);
printf("%p", (void*) (int*)0);
printf("%d", (int *)0);
那么使用错误的格式说明符也是错误的,因为用于打印指针的格式说明符是%p。你是说

printf("%d", (int*)0);
printf("%p", (void*) (int*)0);
printf("%d", (int *)0);
然后由%p打印的结果表示是实现定义的

C标准国家

C11,7.21.6格式化输入/输出函数

该参数应是指向void的指针。指针的值为 转换为打印字符序列,以 实现定义方式

如果第三个printf具有如下所示的精确值:

printf("%d", int* 0);
这将导致编译器错误。然而,如果你的意思是

printf("%d", (int*)0);
printf("%p", (void*) (int*)0);
printf("%d", (int *)0);
问题有两个:

格式说明符用于整数,而不是指针。如果两者大小相同,您将幸运地获得相同的输出。但这实际上是一种未定义的行为。使用%p作为指针。 另一个更普遍的问题是,您通过了。由于指针的整个处理是特定于实现的,因此printf处理它的方式可能不同于有效的指针值。
无论哪种方式,都不能保证堆芯转储或显示任何特定行为。在最坏的情况下,它甚至可能不会显示出任何错误的行为——你不会注意到出了什么问题。未定义行为的本质是任何事情都可能发生。您的计算机可能会飞走。

如前所述

printf( "%d", int* 0 );
不会编译,因为int*0不是合法表达式

如果写为

printf ( "%d", (int *) 0 );
printf( "%p", (int *) 0 );
printf( "%p", (void *) 0 );
printf( "%d", *(int *) 0 );
然后该行为未定义,因为%d希望其对应的参数的类型为int,而不是int*。这很可能不会导致核心转储,但不应信任任何输出

如果写为

printf ( "%d", (int *) 0 );
printf( "%p", (int *) 0 );
printf( "%p", (void *) 0 );
printf( "%d", *(int *) 0 );
该行为仍然未定义,因为%p需要一个void*这是少数几个需要在C中显式将指针值转换为void*的地方之一。同样,这很可能不会导致核心转储,但任何输出都不应受信任

如果写为

printf ( "%d", (int *) 0 );
printf( "%p", (int *) 0 );
printf( "%p", (void *) 0 );
printf( "%d", *(int *) 0 );
然后,它应该为空指针打印出实现定义的值,该值可能不为0,也可能不为0,假设您使用换行符或调用fflush stdout

如果写为

printf ( "%d", (int *) 0 );
printf( "%p", (int *) 0 );
printf( "%p", (void *) 0 );
printf( "%d", *(int *) 0 );

那么这很可能会导致内核转储。严格地说,由于您正在解引用无效指针,因此该行为仍然未定义,并且可能存在这样做不会立即导致崩溃的系统

不,它是独立于平台的。它不在任何平台上编译。int*0应该做什么?@EugeneSh:它会生成一个编译器错误。@Olaf我相信OP有不同的观点。@ChongZheng当然会。这是语法错误。所以不需要堆芯,我有个问题。0是常数。如果int*0返回常量值为0的地址?@ChongZheng No.int*0返回一个int*类型的指针,指向地址0。@TomCarpenter大多数情况下都是这样,但我不确定标准是否能保证……您不必将指针强制转换为void*。实际上,你不应该这样做。@Olaf在我对%p的回答中引用了标准指令。因为printf是一个可变函数,所以没有从int*到void*的隐式转换。所以强制转换是必要的。用%p打印空指针是完全有效的。它不是未定义的;空指针是一个有效的指针。另一个更普遍的问题是,您正在传递一个空指针,这会导致未定义的行为。printf仅定义为打印有效指针,定义的空指针不正确。实现只定义空指针的表示;使用printf打印由标准定义。它谈论无效值,如char*p=0;printf%s,p;,strcpyp,你好,;等等,不是我们在这里讨论的情况。我没有说使用变量改变行为而不是使用文字。我只是举了一些无效值的例子。我确实读了整篇文章。我开始不太确定C中的函数是否要求空参数为空
我再也不在名单上了。仍然使用它,但在以后的标准中可能会有所改变吗?你知道:C++有点。谢谢,你的答案很详细。