【问题标题】:Weird C Syntax 1["ABCDE"]?奇怪的 C 语法 1["ABCDE"]?
【发布时间】:2012-10-12 10:13:12
【问题描述】:

谁能帮我理解下面的代码:

int d = 4;
printf(&d["Hay!Hello %c\n"], &4["BuddyWorld"]);           // Hello (some address in char)
printf(&d["Hay!Hello %c\n"], 4["BuddyWorld"]);            // Hello y
printf(&d["Hay!Hello %s\n"], 4["BuddyWorld"]);            // Segmentation fault
printf(&d["Hay!Hello %s\n"], &4["BuddyWorld"]);           // Hello yWorld

printf("d[Hay!Hello %s\n"], &4["BuddyWorld"]);      
/* warning: passing argument 1 of 'printf' makes pointer 
   from integer without a cast                           */

d[] 或 &d[] 运算符到底是什么? (d 是整数) 为什么&4["BuddyWorld"]4[BuddyWorld] 产生不同的值? (分别为“W”和“y”)

【问题讨论】:

  • a[i]i[a] 都是一样的,*(a + i)。这有帮助吗?
  • 但我仍然不明白为什么&4[BuddyWorld]4[BuddyWorld] 会产生不同的值? (分别为“W”和“y”)
  • @zeroone 4["BuddyWorld"] 是'y',第五个字符。 &4["BuddyWorld"] 是它的地址,即"BuddyWorld" 的地址加上一个偏移量。
  • @isbadawi 你的意思是("BuddyWorld" + 4) 等于&4["BuddyWorld"]"%c" 转换说明符不需要 char 类型的参数(不是 char * 类型)吗?
  • @isbadawi 所说的内容,以及当地址(部分)被解释为int 并打印为char 时,您得到的取决于字符串文字的存储位置,并且当您尝试将字符“y”解释为地址时,它通常不指向您被允许访问的内存,因此是段错误。 - "BuddyWorld" + 4 确实变成了&"BuddyWorld"[4]%c 格式需要 int(这应该是提升 char 的结果)。传递 char* 类型的参数是未定义的行为,但它可以编译,因为通常无法对 printf 参数进行类型检查。

标签: c pointers operators


【解决方案1】:

C 中的下标很奇怪。 a[b]变成*(a + b)(在指针a加上b得到的地址处的东西)。但是,由于a + b == b + a,它也可以反过来工作(a[b] == b[a])。这就是正在发生的一切。特别是,“HelloWorld”实际上是一个指向存储字符串字符的字符数组的指针。

【讨论】:

  • 在前两行中,为什么&4["BuddyWorld"]4["BuddyWorld"] 会产生不同的值?
  • @zeronone - 4["BuddyWorld"] 与“BuddyWorld”[4] 相同——字符“y”(实际上,int 的值为 121)。但是&4["BuddyWorld"] 发生了什么?该表达式是字符串“yWorld”的地址(从偏移量 4 开始的子字符串)。就好像你调用了printf("Hello %c\n", "yWorld"); 当你将一个字符串参数传递给%c 格式转换时会发生什么?它将字符串的地址视为无符号整数并打印相应的 ASCII 字符。我认为你有一个熟悉的角色是一个巧合(我在运行你的代码时没有)。
  • 哦,谢谢,我明白了。这是一个有趣的巧合:)
【解决方案2】:

d["Hay!Hello %c\n"]"Hay!Hello %c\n"[d] 相同。

&运算符给出了指向内容的地址

【讨论】:

    【解决方案3】:

    当您编写类似a[i] 的内容时,它会扩展为*(a + i)。 (我们说a[i]*(a + i)语法糖)。

    加法是可交换的,所以"BuddyWorld"[4] = *("BuddyWorld" + 4) = *(4 + "BuddyWorld") = 4["BuddyWorld"],其中"BuddyWorld" 隐含地代表它在内存中的地址。

    【讨论】:

      猜你喜欢
      • 2017-12-06
      • 1970-01-01
      • 2016-08-26
      • 2012-03-14
      • 2012-12-17
      • 2010-11-24
      • 1970-01-01
      • 2015-08-05
      • 1970-01-01
      相关资源
      最近更新 更多