当前位置: 首页 > 知识库问答 >
问题:

确实如此

广绪
2023-03-14

代码示例:

struct name
{
    int a, b;
};

int main()
{
    &(((struct name *)NULL)->b);
}

这是否会导致未定义的行为?我们可以争论它是否“取消引用为空”,但是C11没有定义术语“取消引用”。

6.5.3.2/4清楚地表明,在空指针上使用*会导致未定义的行为;然而,它并没有对说同样的话-

的语义 -

后缀表达式后跟-

但是,NULL不指向对象,因此第二句似乎未指定。

同样相关的还有6.5.3.2/1:

限制条件:

一元<代码>的操作数

然而,我觉得粗体文本是有缺陷的,应该按照6.3.2.1/1(左值的定义)阅读可能指定对象的左值 - C99搞砸了左值的定义,所以C11不得不重写它,也许这一部分被遗漏了。

6.3.2.1/1确实说:

左值是一个表达式(具有void以外的对象类型),它可能指定一个对象;如果左值在计算时未指定对象,则行为未定义

然而

这一长串的推理似乎表明代码导致了UB,但是它相当脆弱,我不清楚标准的作者的意图。如果事实上他们有什么意图,而不是让我们来讨论:)


共有3个答案

邓浩漫
2023-03-14

让我们从间接寻址运算符 *开始

6.5.3.2 p4:一元 * 运算符表示间接寻址。如果操作数指向一个函数,则结果是函数指示符;如果它指向某个对象,则结果是指定该对象的左值。如果操作数的类型为“指向类型的指针”,则结果的类型为“type”。如果为指针分配了无效值,则一元 * 运算符的行为未定义。102)

*E、 其中E是空指针,是未定义的行为。

有一个脚注说:

102)因此,<代码>

这意味着

C标准没有定义该行为。

如果定义了它,就会出现新的问题,下面列出其中一个问题。C Standard保持未定义是正确的,并提供了一个内部处理问题的宏补偿。

6.3.2.3指针

这意味着值为0的整数常量表达式将转换为空指针常量

但空指针常量的值未定义为0。该值由实现定义。

7.19通用定义

这意味着C允许一个实现,其中空指针将具有一个所有位都已设置的值,并且对该值使用成员访问将导致未定义行为的溢出

另一个问题是你如何评价

邓焱
2023-03-14

是的,这种使用-

只有当第一个表达式指向一个对象时,才会定义该行为,否则就没有定义(=未定义)。一般来说,您不应该在术语“未定义”中搜索更多内容,这意味着:标准没有为您的代码提供含义。(有时它明确指出了一些它没有定义的情况,但这不会改变术语的一般含义。)

这是一种松懈,是为了帮助编译器构建者处理事情而引入的。他们可能定义了一种行为,即使是对于您呈现的代码。特别是,对于编译器实现,对于offsetof宏使用这样的代码或类似的代码是完全可以的。使这段代码违反约束会阻止编译器实现的路径。

公良育
2023-03-14

从律师的角度来看,表达式

从编译器的角度来看,假设编译器程序员没有过度复杂,很明显,该表达式返回的值与< code>offsetof(name,b)返回的值相同,并且我很确定,只要编译无误,任何现有的编译器都会给出这样的结果。

正如所写的,我们不能责怪一个编译器会注意到在内部你使用运算符 -

我的结论是,直到有一个特殊的段落说,只要它只是获取它的地址,它是合法的,请取消引用空指针,这个表达式是不合法的C。

 类似资料:
  • 问题内容: 我看到了无数的示例和教程,这些示例和教程展示了如何通过仅设置文件的权限位来创建文件,并且所有这些文件都“作弊”。我想知道/找出如何在创建/更新文件期间正确实例化os.FileMode以提供给编写者。 下面是一个简单的示例: 在上面的基本功能中,权限位0664被设置,尽管这有时可能有意义,但我还是希望有一种正确设置文件模式的正确方法。从上面可以看到,一个常见的示例是UID / GID是已

  • 我需要使用runOnUiThread来更新UI中的TextView,同时在从WebService获取一些字符串的工作线程中更新TextView。我看了一些其他的帖子,并试图实现提供的解决方案,但当我启动我的应用程序,它崩溃。我不太熟悉这个方法,所以我需要一些方向,如何解决这个问题。

  • 我有一个android应用程序,我正在尝试在其中实现linkedIn登录。LinkedIn SDK已经成功集成,我正在获取用户信息以及电子邮件地址。 以下是我的应用程序在谷歌登录时的工作方式: 1)在手机上获取访问令牌 2)发送带有访问令牌的电子邮件地址到服务器 3) 用我通过谷歌的webapi收到的访问令牌获取用户的详细信息。 4) 如果回复电子邮件与从移动设备接收的电子邮件匹配,则检查该电子邮

  • 问题内容: 我上课很难。麻烦的是,我正在尝试将包裹中的一个成员写入对象,这是一个对象。的是,和对象()在列表中的。 以下是相关代码: 我在“ //帮助这里”标记了两个点,以了解如何正确地写包裹以及如何对其进行重建。如果经过(正确测试),我该如何正确执行? 问题答案: 你差点知道了! 您只需要做: 就这样! 对于您的Integer列表,您还可以执行以下操作: 它应该工作。

  • 我正在寻找关于如何以及何时实现dispose模式的建议。 我已经阅读了MSDN关于如何实现dispose()模式的文章。说得通。我在我的类中实现了它,但它似乎对内存使用没有什么影响。 有点背景,我正在建立一个2D自顶向下的游戏引擎。我有一个名为Gatherer的单元,它继承自Actor(一个用于绘制sprite和跟踪viewplane的基本类),它们是一些简单的sprite。它们在5轮比赛后消失。

  • 返回在下面 我尝试从https://www.elastic.co/guide/en/elasticsearch/guide/current/_finding_exact_values.html按方向进行以下查询