takashiki 发表于 2011-12-26 22:43:56

晕菜!C语言奇特的特性

根据堆栈溢出网站上内容改编成一道C语言测试题,全部做正确很难啊,虽然题目看上去很简单。
C++的更多,Javascript的最多,简直就是不可理喻!

C++版的:
C++1x Lambda表达式:
    [] (int x) { std::cout << x << std::endl; } ();
    调用:[](){}();[]{[]{}();}();
晕菜了没有?还好,现在使用C++1x特性的人还不多。

Javascript版的:
    '5'+3 = '53'
    '5'-3 = '2'
    这个才是超级坑爹的。
    还有,2==[[]]

好了,相信你已经晕的差不多了,现在上正餐,C语言版。没有上面的那么变态,不过也够喝一壶的了。因为C++兼容C89(不兼容C99),下面的内容都是同样适用于C++的。

#include "stdio.h"

int Array[] = {
    123, 456, 789, 012, 345, 678, 901, 234, 567, 890,                   //Array = ?
};

typedef char c;

int main(int argc, char* argv[])
{
    {
      int i;

      for(i = sizeof(Array) / sizeof(int); i --> 0; ){                // -->在这里很直观啊
            printf("%d\n", Array);
      }

      i = 0;
      Array = i;                                                 //到底是先赋值还是先自增?
      printf("i:%d Array: %d %d %d\n", i, 0, 1, 2, 3);    //数组访问有问题吗,有问题吗?
    }

    printf("LOL?" "?"                     "!LOL\n");                  //结果是多少
    printf("LOL" "??!"                     "LOL\n");                  //结果又是多少

    http://www.ourdev.cn                                                直接输入URL,不需要注释

    {                                                                   //代码都变成天书了
      struct c {c c;} c;
      c: c.c = 'c';
      printf( "%c\n", c.c);
    }

    {                                                                   //奇怪的sizeof行为,结果是什么
      int x = 1;
      int sz = sizeof(x++);                                           //sizeof带括号
      char a[] = "Hello";
      int s1 = sizeof a;                                              //sizeof不带括号
      //int ss = sizeof int;                                          //为什么就不行呢?
      int s2 = sizeof ("Hello", a);
      printf("%d %d %d\n", x, s1, s2);
    }

    return 0;
}




附上原始出处:http://stackoverflow.com/questions/1995113/strangest-language-feature?page=1&tab=votes#tab-top

hsztc 发表于 2011-12-26 23:30:51

Array=012=10

0开头为8进制数

XA144F 发表于 2011-12-27 08:47:33

啥玩意儿啊……

takashiki 发表于 2011-12-27 08:52:06

下面是VC(含VC6和VS2005)的执行结果:
890
567
234
901
678
345
10
789
456
123
i:1 Array: 0 456 789
LOL??!LOL
LOL|LOL
c
1 6 4


我只在VC和Keil上测试过,未测试其他编译器。结果如下:

回复【1楼】hsztc
array=012=10
0开头为8进制数
-----------------------------------------------------------------------
对的。

for(i = sizeof(Array) / sizeof(int); i --> 0; )      这里只管看起来就是i从数组最后一个元素递减到0,等价于
for(i = sizeof(Array) / sizeof(int) - 1; i >= 0; i--)
C语言没有-->操作符,i --> 0会被解析成(i--) > 0

Array = i,优先级的问题,貌似跟编译器相关?
VC显示:      i:1 Array: 0 456 789
Keil C51显示:i:1 Array: 1 456 789
Keil MDK显示:i:1 Array: 0 456 789


1 = Array,这是个C语言的奇怪特性,在编程语言的奇怪特性中击败了其他所有语言的奇怪特性荣登榜首。

printf("LOL?" "?"                     "!LOL\n");            直接组合成LOL??!LOL
printf("LOL" "??!"                     "LOL\n");            转义字符不仅有\,还有??,??!会被转义成|,一不小心就会犯错

http://www.ourdev.cn                这个是用来好玩的,http:解析成标号了,//解析成注释


    {                                                                   //代码都变成天书了
      struct c {c c;} c;
      c: c.c = 'c';
      printf( "%c\n", c.c);
    }
这个在Keil C51中编译不通过,VC和MDK中没有问题。


int sz = sizeof(x++);这个我实在分析不出来,VC和Keil都显示结果为1。

ayumi8 发表于 2011-12-27 08:56:42

相当的晕没见过的用法啊我是菜鸟

crazydtone 发表于 2011-12-30 18:17:41

./emotion/em121.gif

first_blood 发表于 2011-12-30 19:56:28

谁写的垃圾程序,你让别人怎么看啊,明天别来上班了。老板如是说

nongxiaoming 发表于 2011-12-30 20:32:29

对javascript个人不觉得晕,那是个解释型语言,不严谨的~你随意写一个语句,它能识别就出结果,不能识别就跳过,这就要求尽可能的去解释你所写的,你写的东西格式压根不对,那它爱出啥就是啥,不出也就算了,‘5’-3=‘2’这类东西,很正常啊,‘5’的ASCII码值减去3本来就是‘2’的ASCII码值啊~

yyccaa 发表于 2011-12-30 22:43:04

int sz = sizeof(x++);这个我实在分析不出来,VC和Keil都显示结果为1。
--------------------------------
因为sizeof()是运算符,在编译阶段就对括号中的类型进行判断,所以编译后直接成了赋值常数给sz,
类似的:

char a={ 1, 2};
int sz=sizeof(0&1);
sz=sizeof(0);
sz=(-1)[&a];

int s2 = sizeof ("Hello", a); 这个是逗号表达式,其实比较常见的形式是变量声明和for语句中,比如
int a=1,b=2;
for(i=0,j=1;i<8;i++,j++)

看这些题目,让我想起了国际C语言混乱代码大赛……

takashiki 发表于 2011-12-31 10:59:34

回复【8楼】yyccaa
-----------------------------------------------------------------------

int sz = sizeof(x++);这个我实在分析不出来,VC和Keil都显示结果为1。
--------------------------------
因为sizeof()是运算符,在编译阶段就对括号中的类型进行判断,所以编译后直接成了赋值常数给sz,
类似的:


哥们我很想同意你的答案,可是不好意思,你的解释是错的。

按照sizeof后面接类型的解释,sizeof(x++)应该为4,但是结果为1。
现在这里有三个运算符:sizeof、()、++,估计编译器的计算顺序是:
sizeof(x++) ==> sizeof(x), x++==> sizeof(1), x++ ==> sizeof(1) = 1, x = 2
但是很不明白。x和x++都是int类型,求sizeof之后应该为4,但是它直接用一个常数代替了。
而且可以肯定的是没有先执行x++,因为sizeof(2) = 2。

takashiki 发表于 2011-12-31 11:13:23

回复【7楼】nongxiaoming
-----------------------------------------------------------------------

哥们你用C去解释Javascript,我很无语啊。照你这意思,'5'+3='8'才对,可是它等于'53'。
再说,Javascript中哪来的字符型?单引号和双引号的都是字符串好不好。

Javascript的字符串重载了+号运算符,没有重载-号运算符,是引起此类问题的根本所在。

'5'-3会被解析成5-3=2,前面的字符串会根据第二个操作数推断转换成数值型,因为数值型才有-号运算符。

举例:'123'-5=118。


同样,C++也可以实现,只不过除了让人犯晕外,没别的用途。这也是微软为什么强制要求C#的操作符重载时必须成对出现的原因。

galanodel 发表于 2011-12-31 12:45:06

晕喽,这个还真没用过

yyccaa 发表于 2011-12-31 13:31:37

按照sizeof后面接类型的解释,sizeof(x++)应该为4,但是结果为1。
--------------------------------------
可惜啊哥们,你没看清printf输出的是哪个变量值:

printf("%d %d %d\n", x, s1, s2);

是 x,不是sz。

Zhhu218 发表于 2012-1-2 09:22:55

晕~~~~~

losting 发表于 2012-1-5 23:30:22

mark

writer15 发表于 2012-1-6 01:54:40

我一般不去理会这些蛋痛的语法,原因是我不会用这些蛋痛的语法。

去钻研这些蛋痛的语法,我觉得是闲得没事做,搞语言开发的专家的事。

就像现在天_朝教育给学生的一样,什么刁钻的数学题都给你做,却一辈子也不会用到,碰到。

当然我肯定当不了也成了不上面所说的专家,我只能够当一个写出浅显易明,可读性强,易维护的代码的普通人。

Earthman 发表于 2014-5-20 16:01:31

有段时间没研究这个了,标记下

wind2100 发表于 2014-5-20 16:05:19

你不会是要参加乱码大赛的吧
页: [1]
查看完整版本: 晕菜!C语言奇特的特性