

gcc 为什么连这种代码都能编译通过?
source link: https://www.v2ex.com/t/860466
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

#include <stdio.h>
int main(int argc, char *argv[])
{
char *s = argv[argc-1];
printf("%s\n", s);
char *s2 = argc[argv-1];
printf("%s\n", s2);
return 0;
}
打印最后一个参数,上面的写法是正确的,问题是下面的写法也能编译通过,而且打印输出和上面的写法一样,不明白为什么编译器允许 argc[argv-1] 这种写法。
realradiolover 9 小时 42 分钟前 管理指针是程序员的责任
|
![]() |
ecloud 9 小时 36 分钟前 x[y]应该等价于 (x 地址数+y*x 定义的位长)的地址
那么这里是不是可以理解 argc 也是个地址,这个传进来的所谓 int 并不在堆里? |
kgdb00 9 小时 35 分钟前 @realradiolover 问题是把 int 类型直接当成数组用,不符合 c 语言的语法规范啊
|
![]() |
XiLingHost 9 小时 34 分钟前 @kgdb00 实际上数组是个语法糖,本质是指针操作
|
![]() |
msg7086 9 小时 32 分钟前 via Android a[b] 就是 *(a+b)。
加法的两端是可以交换的。所以 a[b]就是 b[a]。 |
hardwork 9 小时 31 分钟前 via Android a[3]等价于 3[a],c 语言混乱编码里经常看到,最终都是*(a+3)的意思,至于是不是符合语言规范就不知道了,反正 gcc 可以通过
|
![]() |
adoal 9 小时 31 分钟前 via iPhone 什么类型不类型的,C 又不是 Haskell
|
![]() |
ecloud 9 小时 29 分钟前 这么看起来这段内存是这样的:
argc | argv[0] | argv[1] | ... argv-1 的地址就相当于 argc 的地址 你的 argc 是不是等于 1 呢?你试试它等于 3 的时候是不是就显示不全 argv[0]了 |
![]() |
Caturra 9 小时 27 分钟前 我没看过 C 标准,但是
可不可以这么写是标准负责的事情 要不要这么写是程序员负责的事情 |
knir 9 小时 21 分钟前 翻了一下 C 标准,6.2.5.1 Array subscripting
1: One of the expressions shall have type ‘‘pointer to complete object type’’, the other expression shall have integer type, and the result has type ‘‘type’’. 2: ... The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))) ... |
![]() |
xiri 9 小时 14 分钟前 via Android @ecloud 没有你想的那种巧合,楼上已经讲的很清楚了,因为 a[b]的本质还是指针操作,有:a[b]=*(a+b)=*(b+a)=b[a]
|
qbqbqbqb 8 小时 42 分钟前 首先很显然 (argv-1)[argc] 和 argv[argc-1]访问的是同一个东西。然后根据 C 语言数组下标操作的定义,(argv-1)[argc]和 argc[argv-1]又是等价的。
|
chronosphere 8 小时 32 分钟前 via Android @knir 这种下标运算的写法和结果和汇编语言里的指针寻址很像,可能 C 语言就照搬过来了吧。把 argc 对应的二进制数据看作相应的内存地址,就好理解一些了
|
zyeros1991 7 小时 8 分钟前 跟我一起背:指针是合法的整形,整形是合法的指针
|
![]() |
geelaw 6 小时 47 分钟前 argv[argc-1] 是正确的,这不必多说。
argc[argv-1] 是语法正确的,楼上已经解释过了。然而这段代码是错误的(不可移植),见 C89 2.1.2.2 和 3.3.6 。 2.1.2.2 规定了 int main(int argc, char *argv[]) 的实参含义,满足该要求的实现里,argv 可以是一个长度为 (argc + 1) 的数组,此时依 3.3.6 对指针加减一个整数定义,(argv - 1) 是 undefined behavior ,因为它不能指向 argv 数组的任何一个元素,也不能指向 argv 数组最后一个元素之后的位置。该 undefined behavior 不要求算出的指针被解引用。 注意 argc[argv-1] 等同于 *(argc + (argv - 1)),因此是错误的。但 *(argc + argv - 1) 就不是错误的了(除非 argc 等于 0 )。 |
evan1024 1 小时 42 分钟前 via Android 换 rust😏
|
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK