【问题标题】:Understanding operations with pointer用指针理解操作
【发布时间】:2015-04-08 04:46:50
【问题描述】:

我有一个C语言的sn-p代码,如下图:

#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main() {
    char *s="Abhas";
    printf(" s = %s \n", s);
    printf(" s + s[1] = %s \n", s+s[1]);
    printf(" s + s[1] - s[3]= %s \n", s+s[1]-s[3]);
    return 0;
}

输出是:

那么,您能否帮我澄清一下我们如何获得第二个和最后一个输出行。我是 C 的新人。

【问题讨论】:

  • 期待什么结果?
  • 倒数第二个 printf 由于缓冲区溢出导致未定义的行为,从this answer的第二部分了解一下
  • 其实,我需要解释一下 sn-p 代码是如何工作的,以及为什么我会得到输出。
  • @GrijeshChauhan:我想是的。 s + s[1] = s + 'a' = s + 62 => 错误,因为字符串只有 5 个字符。
  • @PhucNguyen in s + s[1], .. s[1]'b',其 ascii 值为 98(假设 ascii 实现)和 s + s[1] == s + 98 运行时错误

标签: c pointers


【解决方案1】:
printf(" s + s[1] = %s \n", s+s[1]);

相当于:

printf(" s + s[1] = %s \n", s+'b');

相当于:

printf(" s + s[1] = %s \n", s+98);

这将访问它不应该访问的内存。该程序表现出未定义的行为。

行:

printf(" s + s[1] - s[3]= %s \n", s+s[1]-s[3]);

相当于:

printf(" s + s[1] - s[3]= %s \n", s+`b'-'a`);

相当于:

printf(" s + s[1] - s[3]= %s \n", s+1);

相当于:

printf(" s + s[1] - s[3]= %s \n", "bhas");

因此输出。

【讨论】:

  • 是的,没错。我会在 5 分钟后接受你的回答。谢谢
  • 看起来这就是我需要的答案。但我不太明白只有一件事。编译器从上到下,从左到右读取,但是在s + s[1] - s[3]中,为什么先计算s[1]-s[3]?
  • @PhucNguyen,我展示了s[1] - s[3] 的结果只是为了说明。真正的操作将首先是s + s[1],然后是结果上的- s[3]
【解决方案2】:

想象一下这样排列的内存:

   | [0] | [1] | [2] | [3] | [4] | [5] | <- indexes
   +-----+-----+-----+-----+-----+-----+
s: |  A  |  b  |  h  |  a  |  s  | nul | <- characters
   |  65 |  98 | 104 |  97 | 115 |   0 | <- integral values (if ASCII)
   +-----+-----+-----+-----+-----+-----+

下面的表达式-地址映射显示了正在发生的事情:

s                                -> s       -> &(s[0])
s + s[1]                         -> s + 98  -> &(s[98])
s + s[1] - s[3]  -> s + 98 - 97  -> s + 1   -> &(s[1])

其中,只有第一个和第三个是合法的,因为它们最终在字符串的范围内。第二个是未定义的。

第一个给你字符串本身的地址,所以你看到Abhas

第三个给你字符串的第二个字符的地址,所以你看到bhas

第二个给你一些超出字符串的东西,因此会给你它想要的任何东西。事实上,作为未定义的行为,它可以给你任何东西,什么都没有,崩溃,格式化你的磁盘,通过你的声卡疯狂地笑,甚至崩溃到一个赤裸裸的奇点,带走我们星球的一大块。


我当然应该提一下,除了让您了解指针的工作原理之外,该代码应该永远在野外被使用或看到。这是如何编码的经典示例。

【讨论】:

  • 感谢@paxdiablo 的评论。但我必须标记@R Sahu,FIFO 家伙的答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-24
  • 2023-03-09
  • 1970-01-01
  • 2011-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多