C语言中行为未定义的代码# 在C++中,有很多方法可以编写编译的代码,但会产生收益。C#中有类似的东西吗?我们可以用C语言编写代码,进行编译,但有未定义的行为吗?

C语言中行为未定义的代码# 在C++中,有很多方法可以编写编译的代码,但会产生收益。C#中有类似的东西吗?我们可以用C语言编写代码,进行编译,但有未定义的行为吗?,c#,c++,undefined-behavior,C#,C++,Undefined Behavior,看看,未定义行为发生的情况要么是不允许的,要么是在C语言中引发异常 然而,在不安全的代码中,我认为未定义的行为是可能的,因为它允许您使用指针等 编辑:看起来我是对的: 在c#中有一个未定义行为的例子,这并不完全是Wiki意义上的,但我想我脑海中最明显的例子就是简单地编写一些线程代码,但在任何语言中都是这样 一般来说,我会说不 在初始化自动变量之前使用它。 所有变量都必须初始化。如果没有,则会发生异常 除零 异常被抛出 索引超出范围的数组 异常被抛出 正如Aequitarum Custos指出的,

看看,未定义行为发生的情况要么是不允许的,要么是在C语言中引发异常

然而,在不安全的代码中,我认为未定义的行为是可能的,因为它允许您使用指针等

编辑:看起来我是对的:


在c#

中有一个未定义行为的例子,这并不完全是Wiki意义上的,但我想我脑海中最明显的例子就是简单地编写一些线程代码,但在任何语言中都是这样

一般来说,我会说不

在初始化自动变量之前使用它。

所有变量都必须初始化。如果没有,则会发生异常

除零

异常被抛出

索引超出范围的数组

异常被抛出


正如Aequitarum Custos指出的,您可以使用不安全的代码。这也不是真正的C#,您明确地选择退出C#环境

正如其他人所提到的,几乎“不安全”块中的任何东西都可以产生实现定义的行为;滥用不安全块允许您更改组成运行时本身的代码字节,因此所有赌注都被取消

分区
int.MinValue/-1
具有实现定义的行为

抛出异常而从不捕获它会导致实现定义的行为——终止进程、启动调试器等等

在C#中还有许多其他情况,我们被迫发出具有实现决定行为的代码。例如,这种情况:


然而,安全、行为良好的C#程序具有实现定义的行为的情况应该非常罕见

根据ECMA-334文件(第473页):

一种不包含任何代码的程序 不安全修饰符的出现 不能显示任何未定义的 行为


这将“实现定义”提升到最糟糕的情况,请参见Eric Lippert的答案。

是!即使在安全的环境下,也会有!(好吧,它的实现定义至少是未定义的)

这是中Marek Safar和VSadov的一个。在
bool
方面,C#和CLI之间存在不匹配

C认为只有一种
true
,一种
false

CLI认为
false
是一个包含0的字节,所有其他值都是
true

这种差异意味着我们可以强迫C做一些(稍微)有趣的事情:

上述产出:

true

true

false

有趣的是,调试器不同意(必须以不同的方式评估真相?)

无论如何,C#团队得出的结论似乎是(重点补充):

也就是说,该语言将完全不关心非标准布尔值。特定的实现(如CIL上的MS C#)将确认非标准布尔的存在,并将其行为指定为未定义


许多程序和子程序都有如下要求:

  • 当给定有效数据时,生成有效输出

  • 不要发射核导弹或否定时间法则和因果关系,即使给出的输入无效


  • Java和.NET语言的主要设计目标之一是,除非代码使用某些标记为“不安全”的元素,否则通常不需要特别努力来满足上述第二个约束[虽然从时间/因果关系的角度来看,与垃圾收集和
    Finalize
    相关的一些行为可能有点奇怪,但这些行为可以被描述为正常因果关系规则的例外,而不是完全撤销它们]。这种情况与C中的情况非常不同,C中存在多种与数据相关的错误(例如整数溢出)可能导致编译器以任意方式运行,包括做出避免溢出所需的任何假设。超现代C哲学中鼓励的真正可怕的未定义行为在C#或其他.NET语言中并不存在于“不安全”块之外。

    当您声明“Wiki”时,你指的是什么维基?@Jeff Yates:“未定义的行为”问题中的链接指向维基百科。@杰夫·耶茨:是的,我在查看他的维基百科链接,以确定哪些情况会导致未定义的行为。链接已失效,此答案没有任何说明。不安全代码是C#。您选择退出的是托管代码保证。这不是C#不安全{int*px1;int*px2=&i;F(out px1,ref px2);Console.WriteLine(“*px1={0},*px2={1},*px1,*px2);//未定义的行为}是的,它是用C#写的。当然,这是完全合法的C#。C#的一个实现,实现可选的“不安全”子集仍然是C#的一个实现。这只是不确定的,不是未定义的。你仍然可以保证每个线程将要做什么。你只是不知道事情发生的确切顺序,所以你可能会得到一些令人惊讶的结果。@mfloryan:不幸的是,每当你在C#中产生一个新线程时,你都不能期望gNetHack的名字即将开始。啊,你可以通过运行gcc来玩它的好日子…谁说了关于零除法的事?@Eric:我以为你提到的角落案例是通常的1/0。我四处搜索,发现它实际上是
    int.MinValue/-1
    。有人知道或能推测为什么
    int.MinValue/-1
    不是或是co吗语言规范中不能定义吗?@NickStrupat:See@MikeMB:I是的。这是一个微妙的区别
    //non-standard bool
    //We're setting a bool's value to a byte value of 5.
    var a = new bool[1];
    Buffer.SetByte(a, 0, 5);
    
    //non-standard bool
    //We're setting a bool's value to a byte value of 10.
    var b = new bool[1];
    Buffer.SetByte(b, 0, 10);
    
    //Both are true.
    Console.WriteLine(a[0]);
    Console.WriteLine(b[0]);
    
    //But they are not the same true.
    Console.WriteLine(a[0] == b[0]);