Chinaunix

标题: 为什么这样子不报错,或者给一个什么警告也好? [打印本页]

作者: L_kernel    时间: 2011-10-29 23:41
标题: 为什么这样子不报错,或者给一个什么警告也好?
  1. #include <stdio.h>

  2. struct scul_qset {
  3.         int data;
  4.         struct scul_qset* next;
  5. };

  6. int main()
  7. {
  8.         int scul_qset;
  9.         struct scul_qset scul_qset_instance;
  10.         return 0;
  11. }
复制代码
int scul_qset; /* 定义一个和结构标识符相同的变量 */
作者: OwnWaterloo    时间: 2011-10-30 00:12

  1. void x(void)
  2. {
  3.       struct x { struct x* x; } x;
  4. x:
  5.       x.x = &x;
  6. }
复制代码
有一种…… "要是吐槽就输了"的感觉 >_<
作者: nketc    时间: 2011-10-30 00:31
所有这些不在一个概念域中。或者说不在一个名字空间中。从编译器的实现上说他们分属于不同的符号表。

OW吐槽啊,俺就稀饭看你吐槽。
作者: OwnWaterloo    时间: 2011-10-30 00:43
回复 3# nketc

C语言已经是这样子了……  吐也没用……

struct x x; 这种代码倒是经常在一些老的书籍或代码里看见……  这也就算了……
还不如去吐槽那些尽可能"利用"名字空间将人搞晕的代码……
作者: nketc    时间: 2011-10-30 00:48
有时候名字不好起啊。写代码有不少时间都花在怎样给函数,变量,类型命名上了。nnd有时候写测试代码的时候,直接xxx1,xxx2就上了。
作者: davelv    时间: 2011-10-30 00:52
回复 5# nketc

同,还有写注释也花了一些时间。
但是要论起来化在设计/调整设计上的时间还是最多的。
作者: OwnWaterloo    时间: 2011-10-30 00:57
回复 5# nketc

>> 有时候名字不好起啊。写代码有不少时间都花在怎样给函数,变量,类型命名上了。
同感……


>> nnd有时候写测试代码的时候,直接xxx1,xxx2就上了。
我有时候会出现这种状况……

  1. {
  2. // ...
  3.       {
  4.       // ...
  5.             {
  6.             // ...

  7. // 层次太深
  8. // 于是这里干脆从顶重新开始……
  9. {
  10. // ...
复制代码
估计会被很多卫道士反对……
管他呢…… 测试代码而已……
作者: nketc    时间: 2011-10-30 01:01
俺没写过啥复杂的算法,注释一般比较简略。好的命名和排版啥的本身就是注释
当然写算法就另当别论了。

ps-----------
1)看别人代码犯困
2)写代码精神
3)查bug,带劲。

作者: OwnWaterloo    时间: 2011-10-30 01:14
回复 1# L_kernel

无论是好是坏…… C语言已经成这个样子了……
趁着首页还在, 还是正经回复一下吧……


同一个名字/标识符,可以指代不同的东西 —— 无论是否应该这样编写代码 —— 这个应该是蛮常见的。比如:

  1. void f(void)
  2. {
  3.                           /* ^ */     /* ^ */
  4.       int x,y;            /* | */     /* | */
  5.                           /* A */     /*   */
  6.                           /* | */     /*   */
  7.                           /* v */     /*   */

  8.       {                   /* ^ */     /*   */
  9.             double x,z;   /* | */     /*   */
  10.                           /* B */     /* C */
  11.                           /* | */     /*   */
  12.       }                   /* v */     /*   */

  13.                           /* ^ */     /*   */
  14.                           /* | */     /*   */
  15.                           /* A */     /*   */
  16.                           /* | */     /* | */
  17.                           /* v */     /* v */
  18. }
复制代码
在C范围内, y 指代那个 int 变量。
在(两个)A范围内, x 指代那个 int 变量
而中间的B范围内, x 指代那个double变量。 z指代另一个double变量。

这是通过名字出现的位置决定名字指代物。


而 struct x x; 是另一种情况。
是通过名字的种类/作用决定名字的指代物。

  1. struct    /* 有了 struct "前缀" 后续的 */
  2.        x  /* 就是指一个 tag 而不是别的东西 */
  3.           /* 之后的 */
  4.        x  /* 就是一个普通标识符 */
  5.        ;  /* 两者不会冲突 */

  6. x :       /* x 指 label 同样不会冲突 */
复制代码
PS:
对 lable 是函数作用域而不是块作用域感到惊讶的同学,可以问问使用js的同学是什么感受……
对 C语言区分ordinary/member/tag/label 感到惊讶的同学,可以参考lisp-1与lisp-2之间争论。
作者: L_kernel    时间: 2011-10-30 09:46
回复  L_kernel

无论是好是坏…… C语言已经成这个样子了……
趁着首页还在, 还是正经回复一下吧…… ...
OwnWaterloo 发表于 2011-10-30 01:14
感谢回复。说得这么多。困扰我的正是这种
struct x x {};的情况。名字空间这个倒不是我发帖子的目的,不好意思,帖的代码很烂。
作者: nketc    时间: 2011-10-30 09:54
本帖最后由 nketc 于 2011-10-30 09:57 编辑

回复 10# L_kernel


    俺这儿说的名字空间,不是c++或其他语言里的namespace,回复的时候就担心有人误解。
lz的例子虽然名字相同,但是这些名字属于不同的语法范围(这才是俺说的不同的“名字空间”),所以没啥冲突。举个例子,就像聊天用的QQ和某个汽车QQ。
虽然都是水,但井水不犯河水。
-----------------------ps:
这儿的名字空间,是我胡编的,lz别上当。
作者: davelv    时间: 2011-10-30 10:10
回复  L_kernel

对 lable 是函数作用域而不是块作用域感到惊讶的同学,可以问问使用js的同学是什么感受……

OwnWaterloo 发表于 2011-10-30 01:14



这个其实不应该感到惊讶的。咱们用lable就是在函数内部跳来跳去。你可以跳到for循环中,可以跳到if的语句里面。
作者: pmerofc    时间: 2011-10-30 10:14
提示: 作者被禁止或删除 内容自动屏蔽
作者: pmerofc    时间: 2011-10-30 11:05
提示: 作者被禁止或删除 内容自动屏蔽
作者: 幻の上帝    时间: 2011-10-30 12:10
本帖最后由 幻の上帝 于 2011-10-30 13:59 编辑

回复 14# pmerofc
+UINT_MAX+1
+UINT_MAX+2
作者: 幻の上帝    时间: 2011-10-30 12:11
回复 9# OwnWaterloo


话说我能吐槽function scope是专为label name准备的么……
作者: OwnWaterloo    时间: 2011-10-30 12:21
回复 10# L_kernel

struct x x; 的解释确实是名字空间name space(s) —— ordinary/member/tag/label ……
与 C++ 的那个 namespace 不是一回事 —— 貌似我忘记提到这点引起误会了……
作者: OwnWaterloo    时间: 2011-10-30 12:37
回复 12# davelv

第1次实际使用时被惊讶了……

记得是写了一个宏,展开后是内嵌汇编(msvc intel syntax),其代码需要一个label。
测试没问题……
实际使用时,某函数有多个地方使用该宏,就错了……

于是就学会了与 __LINE__ 一起用作 label 的技巧……


js里普通的变量都是function scope的……
scope这种不弄明白就无法编写正确程序的东西, 记得一个stackoverflow的讨论js的帖里被称"区分专家的标志"
作者: OwnWaterloo    时间: 2011-10-30 12:40
回复 15# 幻の上帝

+UINT_MAX+1,不是+0么?
作者: OwnWaterloo    时间: 2011-10-30 12:41
回复 16# 幻の上帝

A label name is the only kind of identifier that has function scope.

ISO C自带吐槽
作者: x5miao    时间: 2011-10-30 13:34
回复 13# pmerofc


    O'Relly的《C in  a Nutsbell》提到了,这本书里面的东西还是很全面的
作者: 幻の上帝    时间: 2011-10-30 13:58
回复 19# OwnWaterloo


    好吧。。一时脑残,+UINT_MAX+2
作者: pmerofc    时间: 2011-10-30 15:11
提示: 作者被禁止或删除 内容自动屏蔽
作者: L_kernel    时间: 2011-10-30 17:22
回复  L_kernel


    俺这儿说的名字空间,不是c++或其他语言里的namespace,回复的时候就担心有人误解 ...
nketc 发表于 2011-10-30 09:54
没有上当,对于名字空间,我不会联想到C++当中的namespace。如果你是使用namespace这个英文单词,估计就会疑惑了。用中文表示“名字空间”,可以有多层意思。中文就是如此,会意的东西比较多。
作者: L_kernel    时间: 2011-10-30 17:26
回复  幻の上帝

+UINT_MAX+1,不是+0么?
OwnWaterloo 发表于 2011-10-30 12:40
+0和-0,这个东西,应该是有符号的时候才考虑吧?
INT_MAX+1
作者: L_kernel    时间: 2011-10-30 17:27
回复  pmerofc


    O'Relly的《C in  a Nutsbell》提到了,这本书里面的东西还是很全面的
x5miao 发表于 2011-10-30 13:34
只看K&R那本第二版,其余的都不想看了。因为那本书一直都没有完全领会。
作者: MMMIX    时间: 2011-10-30 17:45
只看K&R那本第二版,其余的都不想看了。因为那本书一直都没有完全领会。
L_kernel 发表于 2011-10-30 17:27



    一真沒有完全領會估計就是因為其它相關資料看的太少。
作者: MMMIX    时间: 2011-10-30 17:49
+0和-0,这个东西,应该是有符号的时候才考虑吧?
INT_MAX+1
L_kernel 发表于 2011-10-30 17:26



    而且得是有符號的浮點數,整型數一般 +0 和 -0 的表示是一樣的。
作者: L_kernel    时间: 2011-10-30 17:51
一真沒有完全領會估計就是因為其它相關資料看的太少。
MMMIX 发表于 2011-10-30 17:45
是担心被某些资料误导。
作者: L_kernel    时间: 2011-10-30 17:57
而且得是有符號的浮點數,整型數一般 +0 和 -0 的表示是一樣的。
MMMIX 发表于 2011-10-30 17:49
从计算机处理层面上面来讲,不一样吧?
对于有符号数
1000 0000
0000 0000
作者: MMMIX    时间: 2011-10-30 18:01
是担心被某些资料误导。
L_kernel 发表于 2011-10-30 17:51



    看資料也要有選擇,首先中文的絕大多數不要看,其次英文的盡量看官方的,例如 C 標準文檔,GCC 的參考手冊,和口碑好的,例如 Expert C Programming,C: A Reference Manual,等等。
作者: pmerofc    时间: 2011-10-30 18:06
提示: 作者被禁止或删除 内容自动屏蔽
作者: MMMIX    时间: 2011-10-30 18:06
从计算机处理层面上面来讲,不一样吧?
对于有符号数
1000 0000
0000 0000
L_kernel 发表于 2011-10-30 17:57



    你用的啥 CPU (and compiler) 有符號整型數是這種表示方法?BTW,看看這個 http://en.wikipedia.org/wiki/Signed_number_representations
作者: MMMIX    时间: 2011-10-30 18:08
是的。
   刚才翻了一下目录,没找到name space,麻烦给个提示
pmerofc 发表于 2011-10-30 18:06



    你應該查索引的。
作者: pmerofc    时间: 2011-10-30 18:21
提示: 作者被禁止或删除 内容自动屏蔽
作者: MMMIX    时间: 2011-10-30 18:30
没有索引。不知道是不是中译本给阉割了
pmerofc 发表于 2011-10-30 18:21



    肯定是了。這是它的英文目錄:http://my.safaribooksonline.com/book/programming/c/0596006977

我買過清華的兩本英文影印書,都是殘缺的,這出版社的計算機書不能買了。
作者: MMMIX    时间: 2011-10-30 18:33
  (徐波翻译的那本 C语言参考手册 就把索引给阉割了)
pmerofc 发表于 2011-10-30 18:21



    許多中文翻譯的書之所以沒有索引,都是由於譯者+出版商太懶。
作者: pmerofc    时间: 2011-10-30 18:38
提示: 作者被禁止或删除 内容自动屏蔽
作者: 塑料袋    时间: 2011-10-30 18:59
从计算机处理层面上面来讲,不一样吧?
对于有符号数
1000 0000
0000 0000
L_kernel 发表于 2011-10-30 17:57


大哥,你的kernel真是白学了,而且大学的课程也白上了。

任何一个大学的相关课程中,都会讲补码表示法这个基本的东西啊。



每次看讨论C/C++语法相关的帖子,总会看到一帮貌似很深奥的大师们在口若悬河,互相吹捧,颇有佛陀在讲经的感觉。 可不给力的是,到最后经常出现一些最基本,最入门级的原理性错误。
作者: MMMIX    时间: 2011-10-30 19:13
我估计是成本原因,为了省纸,自作聪明地就给阉割了
pmerofc 发表于 2011-10-30 18:38



    這也是個原因吧
作者: OwnWaterloo    时间: 2011-10-30 19:46
回复  幻の上帝
+UINT_MAX+1,不是+0么?
OwnWaterloo 发表于 2011-10-30 12:40

这句话的意思是:
UINT_MAX+1 的结果就是 0。
+UINT_MAX+1 的结果就是 +0 —— 是"加"0,不是"正"0
既没起到+1的作用,也没起到+UINT_MAX的作用。
—— 于是幻の上帝已经修改了。
ls几位……  在想啥呢……
作者: OwnWaterloo    时间: 2011-10-30 19:52
不过既然提到了正负0, 而且MMMIX也给出了一个有符号数可能表示法的wiki链接, 这里就再多说一句。

对某些可能产生正负两种零的有符号数表示法, ISO C是有所准备的。
想想为什么 ISO C只保证short能表示的范围至少有[-32767,+32767] 而非[-32768,+32767] ?
对signed char,int,long也类似。
作者: x5miao    时间: 2011-10-30 22:30
回复 32# pmerofc


    第一章标识符下面一小节有讲“标识符的命名空间”
作者: pmerofc    时间: 2011-10-30 22:37
提示: 作者被禁止或删除 内容自动屏蔽
作者: L_kernel    时间: 2011-10-31 07:52
大哥,你的kernel真是白学了,而且大学的课程也白上了。

任何一个大学的相关课程中,都会讲补码表示 ...
塑料袋 发表于 2011-10-30 18:59
所以现在要重新捡起来。
作者: 天依然很蓝    时间: 2011-11-01 09:35
确实很难的东西  搞不懂
作者: wangzhen11aaa    时间: 2011-11-02 22:16
回复 2# OwnWaterloo
好神奇的想法。coding style就是为了防止类似的犯罪吧。
作者: 狗气球    时间: 2011-11-03 09:53
本帖最后由 狗气球 于 2011-11-03 10:12 编辑
所以现在要重新捡起来。
L_kernel 发表于 2011-10-31 07:52



    别理会塑料袋。信他你就废了。
    “举凡有符号数必补码”←没正经学C很容易有这种看法。

    C标准里对于有符号数的表示给了三种方法。没说非要用补码。

        For signed integer types, the bits of the object representation shall be divided into three
        groups: value bits, padding bits, and the sign bit. There need not be any padding bits;
        there shall be exactly one sign bit. Each bit that is a value bit shall have the same value as
        the same bit in the object representation of the corresponding unsigned type (if there are
        M value bits in the signed type and N in the unsigned type, then M £ N). If the sign bit
        is zero, it shall not affect the resulting value. If the sign bit is one, then the value shall be
        modified in one of the following ways:
        — the corresponding value with sign bit 0 is negated;
        — the sign bit has the value -2N ;
        — the sign bit has the value 1 - 2N

从计算机处理层面上面来讲,不一样吧?
对于有符号数
1000 0000
0000 0000
L_kernel 发表于 2011-10-30 17:57

    你说的这种就是第一种情形“the corresponding value with sign bit 0 is negated;”。
    虽然这种 实现 做法很罕见,也不能说就不可能。
    一般你能看见的C都采用补码,属于第二种情形“the sign bit has the value -2N ;”。

***

    刚写完上面这段,总觉得有啥地方不对劲。
    想想,我说了“实现”俩字儿。
    怎么说,实现一般都会对应到implementation。
    那么就有可能让人觉得我把有符号数表示方法认为是implementation defined了。(虽然仔细推敲并没有这个意思)。
    不是,真不是!{:3_203:}
作者: 狗气球    时间: 2011-11-03 10:04
这句话的意思是:
UINT_MAX+1 的结果就是 0。
+UINT_MAX+1 的结果就是 +0 —— 是"加"0,不是"正"0 。
既没起到+1的作用,也没起到+UINT_MAX的作用。
—— 于是幻の上帝已经修改了。
ls几位……  在想啥呢……
OwnWaterloo 发表于 2011-10-30 19:46



    看到这里真有一种你吐槽就输了的感觉
作者: fred_56    时间: 2011-11-03 10:28
不使用typedef后就不能用同名变量了么?
作者: L_kernel    时间: 2011-11-03 12:40
别理会塑料袋。信他你就废了。
    “举凡有符号数必补码”←没正经学C很容易有这种看法。

  ...
狗气球 发表于 2011-11-03 09:53

很清楚的解释,非常感谢。

对于implementation,也许你该这么说。
It's rarely you wrote in this method.

至于塑料袋的,没正眼看过,好多CU的帖子都看到他在那里不知道做什么。

只是不想让自己的文字带有任何的攻击或者挑衅成分。
作者: OwnWaterloo    时间: 2011-11-04 20:15
回复 49# 狗气球

算我的错……  不该把一些网络俚语搬到网络上来用…… 233……




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2