C ++中的原始类型与C中的原始类型[重复]

Posted

技术标签:

【中文标题】C ++中的原始类型与C中的原始类型[重复]【英文标题】:Primitive types in C++ vs in C [duplicate] 【发布时间】:2020-07-07 11:00:00 【问题描述】:

在 C++ 中,具有原始类型(intdoublechar、...)未定义的未定义行为。原始类型没有默认值,因为它们没有构造函数。但是当没有 context 时,编译器始终给出默认值 (0):

int main()
 int x;
 std::cout << x << std::endl;

总是会给出0(编译后的cc -lstdc++)。

但是,有一些 context(即不只是打印它),值是随机的:

#include <algorithm>
#include "student.hpp"

using std::max;

int main()
    int x;
    Student_struck s = .name = "john";
    std::cout << max(s.name.size(), (std::size_t)x) << std::endl;

这里,同样的编译,但每次的结果都不一样:

21898, 22075, 22020, 21906, ...

原始未定义变量的 gcc 实现是什么?

更奇怪的是,与C相比,我可以拥有

#include <stdio.h>

int main()
    int i;
    printf("%i\n",i);

并且编译器始终一致,将0 作为默认值。因此,相同的编译器,但相同原始类型的不同语言会给出不同的结果。我真的很想知道 C++ 库处理未定义的 primitive 变量的实现是什么。

C 中的原始类型与 C++ 中的原始类型有什么区别。我不是在问 UB,而只是问这些类型是如何用两种语言定义的以及它们之间的区别

【问题讨论】:

不,编译器唯一一致的就是making demons fly out of your nose。这是未定义的行为。今天你可能会得到 0。明天你可能会得到 42。第二天你的电脑可能会着火。这就是未定义行为的含义。 您的问题是关于 C++ 规则还是为什么 GCC 有这种行为? 很可能与下面的内存有关。创建另一个变量将int x 推送到不同的内存位置可能会发生这种情况,那里有一些剩余物(可能是调用构造函数后的剩余堆栈)。但是,与所有未定义的行为一样,它可能是它想要的任何东西。 "原始类型没有默认值,因为它们没有构造函数。" - 具有静态或线程本地存储持续时间的对象获取zero-initialized,因此由只是让它static int x;你会有一个零初始化的x 许多编译器会在 debug 构建中初始化值 0,但在优化构建中不会这样做。尝试开启优化,事情可能会发生变化。 【参考方案1】:

在 C++ 中,具有原始类型(intdoublechar、...)未定义的未定义行为。

我认为您的意思是未初始化 - 只是让它们未初始化并不是未定义的行为。事实上,当您知道会在稍后阅读它们之前为它们分配一个值时,这种情况很常见。

原始类型没有默认值,因为它们没有构造函数。

具有静态或线程本地存储持续时间的对象获取zero-initialized。

与 C 相比,我可以...

您已经观察到您的程序可以具有的许多允许行为中的一种特定行为。 C 标准说:

[6.7.9]/10 C 中的初始化(重点是我的):

如果具有自动存储持续时间的对象未显式初始化,则其值不确定

如果具有静态或线程存储持续时间的对象未显式初始化,则:

——如果是指针类型,则初始化为空指针;

——如果是算术类型,则初始化为(正或无符号)零;

——如果是聚合,则每个成员都根据这些规则(递归地)初始化,并且任何填充都被初始化为零位;

——如果是联合,则根据这些规则(递归)初始化第一个命名的成员,并将任何填充初始化为零位;

看来你的假设是错误的。编译器不需要保持一致。它在程序的不同部分可能会有所不同,具体取决于优化标志和星期几等。

【讨论】:

从技术上讲,呈现的 C 代码仍然是未定义的行为,但 not from the reasons one expects。 @KamilCuk C++ 代码?当然,我毫不怀疑。在C中,我不知道。没有陷阱表示的风险。你的意思是它可能在一个寄存器中(即使register 没有被使用),因为它的地址没有被占用,因此读取它有UB?如果是这样的话,我可以买那个。 Do you mean...? 是的。【参考方案2】:

编译器始终给出默认值 (0)

也许,但这是你不能依赖的。

原始未定义变量的 gcc 实现是什么?

如果不查看源代码并跟踪执行以查看在您的特定情况下会发生什么(优化标志、编译器版本、输入代码...),很难说。

而且编译器总是一致的,默认值是0。

尝试添加代码,您可能也可以使用 C 看到“随机”值。

因此,相同的编译器,但对于相同的原始类型,不同的语言会给出不同的结果。

您使用相同的编译器这一事实并不能保证行为将始终成立。即使您始终使用完全相同的编译器版本和相同的构建标志,行为也可能会因不同的输入代码而改变。

【讨论】:

我认为这个问题之前已经在网站上被反复询问和回答过。例如,请参阅this。我认为我们不需要再次回答。 @_Static_assert 你是不是有点紧张了?这不是那么难的问题,不是吗? @mil 您的问题没有任何研究迹象。 Stack Overflow 不欢迎此类问题。 @milanHrabos 多次回答问题会使其他人更难找到问题并保持答案的相关性。想象一下,例如 C++23 标准将决定所有变量都应该被初始化,现在我们需要找到每一个重复的问题并在那里更新答案以反映当前的艺术状态。 @_Static_assert 我已经编辑了这个问题。您对不同问题的建议是针对普通的c++。我的问题是两种语言之间的比较,cc++。那不一样

以上是关于C ++中的原始类型与C中的原始类型[重复]的主要内容,如果未能解决你的问题,请参考以下文章

java自学篇

JNI签名与数据匹配

认识编程语言中的数据类型

大数据技术能力提升_2numpy的学习

c#静态类中的8个可为空的引用类型

JavaScript中的“符号”原始数据类型是啥[重复]