在你看来,你遇到过的最令人惊讶、最怪异、最奇怪或最“WTF”的语言特性是什么?

请每个回答只回答一个特征。


当前回答

一般来说,弱类型。

C:

printf("%c\n", 'a' + 3);

PHP:

echo 5 + "3";

还有太多其他语言。

其他回答

好吧,既然问题是断断续续的,我就加入到“有趣”中来

Go(又名Issue9)使用大写的可见性:

如果你用大写字母命名某个东西,它就会被公众访问。 如果你使用小写,它将被包保护:

包装外可见:

func Print(v ...) { 
}

包外不可见

func print( v ... ) {
}

你可以在这个原始答案中找到更多。

这不是一个奇怪的功能,事实上,如果你仔细想想,它是完全有意义的,但还是给了我一个WTF时刻。

在c++(和c#)中,基类的子类不能访问基实例上的私有和受保护成员。

class Base {
protected:
 m_fooBar;
};

class Derived: public Base {
public:
 void Test(Base& baseInstance) {
  m_fooBar=1; //OK
  baseInstance.m_fooBar = 1; //Badness
  //This, however is OK:
  ((Derived&)baseInstance).m_fooBar = 1; //OK
 }
};

在awk中,数组从索引1开始,这是最不容易混淆的。

在Java中,

String s = null;
System.out.println(s + "hello");

输出“nullhello”。

Forth的控制结构有些奇怪。首先,因为它是一种反向波兰符号语言,条件在IF之前,如:

x 0 = IF

现在,要关闭条件块,使用关键字THEN:

x 0 = IF ." Equals zero!" THEN

现在真正的WTF开始了。IF所做的是编译一个有条件的前向跳转,并将跳转偏移量的地址放在堆栈上。当找到THEN时,它从堆栈中弹出该地址,计算实际偏移量,然后编译它。另一方面,ELSE编译一个条件向前跳转,从堆栈中弹出一个地址,将一个新地址压入堆栈,计算弹出地址的偏移量,然后编译该偏移量。这意味着语法是这样的:

x 0 = IF ." Equals zero!" ELSE ." Not equal to zero!" THEN

第一个和第二个语句是这样编译的:

x LITERAL 0 = (0BRANCH) LITERAL offset SLITERAL" Equals zero!" (DOTQ)
x LITERAL 0 = (0BRANCH) LITERAL offset SLITERAL" Equals zero!" (DOTQ) BRANCH LITERAL offset SLITERAL" Not equal to zero!" (DOTQ)

更奇怪的是,这种行为并不隐藏。它是该语言的ANSI规范的一部分,可以通过构造自定义流控制结构或以有趣的方式组合它们来自由利用。例如,Forth的WHILE循环:

BEGIN x 10 < WHILE x 1+ to x REPEAT

BEGIN和WHILE之间的部分是任意代码,因此实际上可以在单个控制结构中让代码在条件测试之前和之后执行。这是故意的,但下面的内容虽然是允许的,但却不允许:

BEGIN DUP 2 > WHILE DUP 5 < WHILE DUP 1+ REPEAT 123 ELSE 345 THEN 

它利用了每个控制流字的工作方式来组合两个WHILE语句,并为每个出口添加不同的后循环代码来引导。为了表明我不是在开玩笑,我只是从互联网上的一个代码中复制了这个小片段,并进行了一些小的修改来简化它。