user-0 提问: 二维数组名，是指针的指针，对么？

回复:
user: user-1
content: 引用 126 楼 lin5161678 的回复:[quote=引用 114 楼 williamhong 的回复:]  有一点你一直没弄清楚  改或不改 和 能不能写在赋值符号左边  根本没关系  ++i 这个也会改了 i 但根本和赋值符号没关系  i = i 这个 i 放在赋值符号左边 但是 i 根本就没改  看得清楚吗?  能改 不能说明 可以放在赋值符号左边  能不能放在赋值符号左边的验证方式就是 tmp = tmp 这个表达式能不能通过编译  理清楚思路 别傻傻的卖萌  [/quote]  i = i; Here, value of the object which 'i' designate is NOT changed,but IS modified. n1570, 3.1 NOTE 2 ‘‘Modify’’ includes the case where the new value being stored is the same as the previous value.

user: user-1
content: 引用 129 楼 my_live_123 的回复:引用 50 楼 sholber 的回复:[quote=引用 34 楼 my_live_123 的回复:] [quote=引用 28 楼 sholber 的回复:] [quote=引用 27 楼 williamhong 的回复:] [quote=引用 22 楼 lin5161678 的回复:] [quote=引用 21 楼 williamhong 的回复:] 所有的数组名都仅仅是个地址且不是左值数组名 还真是一个左值 你能把数组名放到等号的左边吗？可以对数组名赋值吗？[/quote] 你知道有个术语叫“可修改的左值”吗？ 你知道有的左值不可修改吗？[/quote] 你是不是想说const修饰符呢？[/quote] 首先， const是类型限定符，不叫修饰符。 其次，可修改的左值和不可修改的左值，与类型限定符没有一毛钱关系。[/quote] 没有引用标准不是你的风格那[/quote]  好吧，不才就引用一哈子。 N1570，6.7.3 Type qualifiers Syntax type-qualifier:     const     restrict     volatile     _Atomic Qualifier，俺们认为译做限定符；修饰符那是Modifier。 引用标准不是错，这叫有据可查。回答人家问题，俺说了一大堆，没有出处，说错了等于放屁不论，主要是误人子弟。不才兄弟我看到外国网站，譬如stackoverflow，人家都是引用标准来证明自己不是胡说八道，如今西风东渐，好的做法一定要借鉴，汝尚有何说？唵？

user: user-2
content: 引用 50 楼 sholber 的回复:引用 34 楼 my_live_123 的回复:[quote=引用 28 楼 sholber 的回复:] [quote=引用 27 楼 williamhong 的回复:] [quote=引用 22 楼 lin5161678 的回复:] [quote=引用 21 楼 williamhong 的回复:] 所有的数组名都仅仅是个地址且不是左值数组名 还真是一个左值 你能把数组名放到等号的左边吗？可以对数组名赋值吗？[/quote] 你知道有个术语叫“可修改的左值”吗？ 你知道有的左值不可修改吗？[/quote] 你是不是想说const修饰符呢？[/quote] 首先， const是类型限定符，不叫修饰符。 其次，可修改的左值和不可修改的左值，与类型限定符没有一毛钱关系。[/quote] 没有引用标准不是你的风格那

user: user-2
content: 没有引用标准不是你的风格啊

user: user-3
content: 可以让他输出11111111111111111111的  改变一下printf不就可以了吗  生命短暂  少些争执   多些合作  鼠侠兄弟  你觉得记住c语音操作符的优先级有意义吗?

user: user-1
content: 引用 118 楼 williamhong 的回复:[quote=引用 116 楼 sholber 的回复:] # include <stdio.h>  int main (void) {     char s [1];     printf (s); } 我肯定这个程序输出“1111111111111111111”，你来验证一下吧。 }  就一次执行而严，执行到printf (s)时的堆栈的内容也一定的吧，怎么不能验证它输出的是什么？别动不动说别人肤浅，软件是有0和1堆积成的，都是确定的，没有不可验证的，这样软件业的真理。 [/quote] 你又错啦！大错特错。 按你的“验证”标准，软件都是由电子堆积而成，而不是你所说的0和1，这是确定的，这是软件业的真理。怎么能怪别人说你肤浅。 显微镜可以观察原子内部，你能用镊子把0和1从堆栈中夹出来吗？你不试试，怎么能验证呢？

user: user-4
content: 引用 116 楼 sholber 的回复:# include <stdio.h>  int main (void) {     char s [1];     printf (s); } 我肯定这个程序输出“1111111111111111111”，你来验证一下吧。 }  就一次执行而严，执行到printf (s)时的堆栈的内容也一定的吧，怎么不能验证它输出的是什么？别动不动说别人肤浅，软件是有0和1堆积成的，都是确定的，没有不可验证的，这样软件业的真理。

user: user-1
content: 引用 112 楼 zhao4zhong1 的回复:没有绝对的真理，只有相对的真理。 从宇宙诞生到现在，发生过哪怕一次绝对无误的1+1=2吗？  这又开始玩脑筋急转弯了。 当我们说一加一时，那就是讨论数学。不是化学。 我们承认真理是需要探索的。概念也是与时俱进的。但是概念一旦提出，那必定是对前期探索的总结。如果你不服，也可以给出一个更好的概念，如果大家都认可，概念会进一步完善，而你善莫大焉。 怕就怕，你自己提不出来，还不承认已有的概念，胡搅蛮缠，多可怕。

user: user-5
content: 引用 114 楼 williamhong 的回复:  有一点你一直没弄清楚  改或不改 和 能不能写在赋值符号左边  根本没关系  ++i 这个也会改了 i 但根本和赋值符号没关系  i = i 这个 i 放在赋值符号左边 但是 i 根本就没改  看得清楚吗?  能改 不能说明 可以放在赋值符号左边  能不能放在赋值符号左边的验证方式就是 tmp = tmp 这个表达式能不能通过编译  理清楚思路 别傻傻的卖萌

user: user-5
content: 引用 114 楼 williamhong 的回复:第2个是错误啊，说明啥呢？ 还问说明啥?  你说 "所有左值都能放在赋值符号左边" 现在就存在一个左值tmp 不能放在赋值符号左边  这当然就是说明 你说得是错的  后面的那些东西我为什么要去否认  那些东西是真是\假 都不影响 存在左值不能放在赋值符号左边这一事实  你的逻辑水平 根本就处于没入门的水平  太笨了

user: user-1
content: 引用 122 楼 u010936098 的回复:[quote=引用 121 楼 sholber 的回复:] [quote=引用 120 楼 zhouchongzxc 的回复:] 可以让他输出11111111111111111111的  改变一下printf不就可以了吗  生命短暂  少些争执   多些合作  鼠侠兄弟  你觉得记住c语音操作符的优先级有意义吗? 我觉得还是有意义的，前提是你能记住。 记得有本书说过，用添加括号的方法虽然可以完全避免这类问题，但表达式中有太多的括号反而不容易理解。 [/quote] 表达式中有太多括号确实不容易理解，但这种表达式把括号去掉也不会太好理解，应该拆分成子表达式并赋值给具有有意义名字的变量。  未定义行为没什么好讨论的，就是符合语法但行为不可预知的代码。讨论它可不可以在“一次运行过程中可不可以验证”毫无意义，只有在运行之前就可以确认其行为的代码才是有意义的，因为我们毕竟不是在运行的同时去编程。[/quote] 后面的一段我接受。 不过通过添加“变量”的方式来解决表达式不易理解的问题，可能有点饮鸩止渴了。 C的优点是表达能力强。如果不发挥这个优势，代码拖沓可憎倒还在其次，效率也不高。这在C标准的附件中尤其提到效率问题。C标准的修改，有时候也要让位于效率。 另一方面，我也不赞同单纯为了好理解而拆解一些紧凑的表达式，尽管它有时看起来很不好理解。在这个时候，加个注释，也许能好点？

user: user-6
content: 引用 121 楼 sholber 的回复:[quote=引用 120 楼 zhouchongzxc 的回复:] 可以让他输出11111111111111111111的  改变一下printf不就可以了吗  生命短暂  少些争执   多些合作  鼠侠兄弟  你觉得记住c语音操作符的优先级有意义吗? 我觉得还是有意义的，前提是你能记住。 记得有本书说过，用添加括号的方法虽然可以完全避免这类问题，但表达式中有太多的括号反而不容易理解。 [/quote] 表达式中有太多括号确实不容易理解，但这种表达式把括号去掉也不会太好理解，应该拆分成子表达式并赋值给具有有意义名字的变量。  未定义行为没什么好讨论的，就是符合语法但行为不可预知的代码。讨论它可不可以在“一次运行过程中可不可以验证”毫无意义，只有在运行之前就可以确认其行为的代码才是有意义的，因为我们毕竟不是在运行的同时去编程。

user: user-1
content: 引用 120 楼 zhouchongzxc 的回复:可以让他输出11111111111111111111的  改变一下printf不就可以了吗  生命短暂  少些争执   多些合作  鼠侠兄弟  你觉得记住c语音操作符的优先级有意义吗? 我觉得还是有意义的，前提是你能记住。 记得有本书说过，用添加括号的方法虽然可以完全避免这类问题，但表达式中有太多的括号反而不容易理解。

user: user-4
content: 引用 62 楼 sholber 的回复:[quote=引用 61 楼 williamhong 的回复:] [quote=引用 60 楼 sholber 的回复:] 简言之，左值是一个指示对象的表达式。 只是解释，不算定义，而且很含糊，哪个表达式又不指示一个对象呢。左值在历史上最原始的定义就是出现在赋值等号左边且有存储地址，且这个地址是供等号右边右值用于写入的地址。[/quote]  5 = 2 这里，5、2和5=2是三个表达式，它们指示对象吗？ 爱咋咋地，你愿意咋想就咋想吧，不关我的事，除非你给money。[/quote]  5 = 2是表达式吗？ 无语了。 说到对象，先给个对象的定义

user: user-4
content: 引用 65 楼 lin5161678 的回复:另外 你自己说了 赋值符号左边的不一定是左值 这个话我什么时候说过？该说的都说了，只能引用以前说过的话 这里是我说的，应该都是对的 我坚持一直都没有改变： 1. 数组名都仅仅是个地址且不是左值 2. 所有左值都可以放到等号左边，所有不能放到等号左边的都不是左值。const的限制和左值没有关系，是不是左值和加不加const也没关系，const约定只能初始化是赋值一次而已，而且不妨碍用指针的方式对声明了const的东西赋值  而下面开始都是你说的，没有一句对，枉你还看过标准。 1. 无知就是无知 居然以为谭浩强说得对（针对网友说的《<引用谭浩强版C++程序设计原话>数组名代表该数组元素的首地址！！！！》话） 2. “数组名 还真是一个左值 3. “(void*)0x12345670 不是什么地址  这个表达式在C语言里面的身份就是一个 堂堂正正的 指针 4. “数组名毫无疑问必须是一个左值

user: user-4
content: 引用 82 楼 lin5161678 的回复:struct Foo {     const int n;     char str[24]; }tmp; tmp = tmp; // 这个tmp是左值 但是这个tmp 不能作为赋值符号的左操作数 看得懂吗   struct Foo {     const int n;     char str[24]; }tmp; int main(int argc , char *argv[]) { struct Foo tmpnew; *(int*)&((struct Foo*)&tmpnew)->n = 0; ((struct Foo*)&tmpnew)->str[0] = 0; memset(&tmpnew, 0, sizeof(struct Foo));  用上面代码也能改，可能不同平台也有差别

user: user-4
content: 你可能用的c++编译器，也说明关于左值各个编译器实现有差别 用这个  int main(int argc , char *argv[]) { const int i = 99; *(int*)&i = 88; printf("%d, %d\n",i, *(int*)&i);}  在不同平台有差别的

user: user-1
content: 引用 115 楼 williamhong 的回复:[quote=引用 110 楼 sholber 的回复:] 不过，就今天而言，最荒谬的是他认为‘未定义的行为’可以验证 顺便纠正一下，‘未定义的行为’是指标准未定义，而不是验证不了，验证也很容易，就用你手里的编译器。软件是有0和1堆积成的，都是确定的，没有不可验证的。[/quote]  纠正？你对所有的术语理解得总是那么肤浅。 所谓“可验证”，广义上来说，如果观察语句能够在对一个语句的验证方面作出肯定或否定的回答,那么这个语句是可以验证的。 既然一个行为是未定义的，那么观察和测量的结果不可能加以肯定和否定，也不具有固化的特性。反之，则是不可验证的。  以下： # include <stdio.h>  int main (void) {     char s [1];     printf (s); } 我肯定这个程序输出“1111111111111111111”，你来验证一下吧。 }

user: user-5
content: 纠正 foo(;a = 99;) 应该是 for(;a = 99;)

user: user-5
content: 引用 80 楼 williamhong 的回复:编程还要我教？下面是代码，拿去运行  int main(int argc , char *argv[]) { const int i = 99; ++*(int*)&i; printf("%d\n",i); }  果然贴一段错误的代码 秀下限  对未定义行为 一无所知的 表现 多用点心呐  来 继续打脸 让你看看什么叫做 错误的代码   无知少年 引用还有前面帖子你为什么只举全局初始化的特例呢，把语句放到函数里就不就和赋值一样了吗？ 一样 ? 哈哈哈  for(;int a = 99;)// err int a = 99 这个声明无法写在 for(;;) 的2个分号中间 ; foo(;a = 99;)//OK a = 99 赋值表达式可以写在for(;;)2个分号中间 ; 引用和你说那么多费劲，还要写代码证明。 该说的都说过了，内容前面都有，你不是说有不能放到等号左边的左值吗？让你举一个怎么总是支支吾吾？ 支支吾吾? 我贴的代码 你假装看不见 我有什么办法 前面早就贴了一个左值不能写在赋值符号左边的  struct Foo {     const int n;     char str[24]; }tmp; tmp = tmp; // 这个tmp是左值 但是这个tmp 不能作为赋值符号的左操作数 看得懂吗