【问题标题】:C Pointer Arithmetic on Characters字符上的 C 指针算法
【发布时间】:2011-02-28 22:20:55
【问题描述】:

我有以下代码在我初始化 ch 的行崩溃:

    char * p = "Test";
    char ch = *p++;
    printf("Here : %s\n%c", p, ch);

但是下面的代码没有问题:

    char * p = "Test";
    char ch = *p++;
    ch++;
    printf("Here : %s\n%c", p, ch);

【问题讨论】:

  • char p_data[] = "Test", *p = p_data; 为您提供您自己的字符串数据副本,允许您对其进行修改。
  • 也许第一段第2行的编辑应该颠倒过来。它使阅读这个问题感到困惑。对于其他人来说,第一段的第二行原本是“char ch = (*p)++;”。

标签: c pointers


【解决方案1】:

在第一种情况下,您尝试更改编译到程序中的“Test”字符串中的T,该字符串保存在您的代码不打算更改的内存部分中(通常;那里是一些允许的环境,但通常不允许)。那是因为(*p)++ 表示(松散地说) *p = *p + 1(例如,获取p 指向的字符,将其递增,然后将其写回),当然,*p 是指向已编译的“Test”。

您的第二个版本没有这个问题,因为您正在递增ch,您可以更改它。实际上,您的第二个版本实际上增加了两个不同的东西;首先它执行char ch = *p++;,它检索*p 处的字符,然后递增p(现在它指向“Test”中的“e”),然后执行ch = ch++。 (您可能只是指ch++;,因为++ 直接对其操作数进行操作。)

【讨论】:

  • 但是如果我不写const char * p,那为什么不允许我通过p改变字符串呢?
  • @Swaranga:因为 C 的定义方式和程序加载到内存中的方式。操作系统将内存分为,可以是“代码”或“数据”(或其他几个我不会涉及的)。您正在尝试更改存储在代码段中的数据,这会导致访问冲突——在 99.999999% 的情况下,程序修改代码段是不合适的。您的第二个示例将代码段中的字符复制到允许修改它的区域(堆栈)中。
  • @Swaranga Sarma:因为使字符串“Test”只读的不是编译器而是链接器。将文本段(即程序+常量字符串数据)标记为只读的是链接器,而强制只读状态的是操作系统。
  • 我应该说(现在已经)这不是普遍正确的。在某些环境中,您可以直接修改该数据。但它们通常是嵌入式系统等。
  • @aaz:是的,我认为它可能是 BSS(取决于实施)。无论如何,这是他不应该改变的东西(通常)。
【解决方案2】:

问题归结为运算符优先级和括号()的使用。

char ch = (*p)++;

此行将(尝试)增加存储在p 中的地址处的字符

char ch = *p++;

这个设置ch等于p中存储的地址处的字符,然后增加p中存储的地址。 ++ 操作符优先于指针解引用操作符,因此它将首先执行。为了清楚起见,第二行相当于:

char ch = *(p++);

【讨论】:

  • 或者换句话说,第二行等于*(p++)
  • @Swaranga Sarma:(*p)++ 表示“在地址 p 的 字符 上加一”,而ch++ 表示在 地址上加一> ch.
  • @averell:好电话。我将其添加到我的答案中。
  • @Swaranga:因为你可以更改ch;你无权更改*p
  • @T.J.克劳德:这是一个很好的观点。这里有两件事。一:指针解引用的错误使用,二:尝试修改 const char
【解决方案3】:

您的第一个示例增加了*p 的值。由于 p 指向一个字符串常量,因此许多编译器都不允许这样做。

你的第二个例子增加了指针,而不是它指向的值。

【讨论】:

    【解决方案4】:

    这段代码:

    (*p)++

    正在尝试增加 p 指向的值。 p 指向 const char 字符串“Test”,不能修改。

    【讨论】:

    • char * p 未声明为 const
    • 不能在他的特定编译器中,在他的特定操作系统上修改它。一些编译器/平台组合将允许它。
    • @Swaranga - p 未声明为 const,但 p 指的是字符串文字“Test”,它位于只读内存页中。
    【解决方案5】:

    第一个版本是这样做的:

    char * p = "Test";  //this should really be const char *
    *p = *p + 1;  //CRASH! attempthing to modifiy the contents of a string literal
    char ch = *p;
    ch = ch++;  //This is excessive, ch++ on it's own would do the same
    printf("Here : %s\n%c", p, ch);
    

    虽然第二个版本是这样做的:

    char * p = "Test"; //still should be const char *
    char ch = *p;
    p++; //p now points to "est"
    ch = ch++;
    printf("Here : %s\n%c", p, ch);  //prints est\nU
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-13
      • 2011-04-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-06
      • 2011-05-09
      相关资源
      最近更新 更多