一起在指针上使用前缀和后缀时的奇怪输出

Posted

技术标签:

【中文标题】一起在指针上使用前缀和后缀时的奇怪输出【英文标题】:Weird output when use prefix and postfix on pointer together 【发布时间】:2015-04-13 22:18:53 【问题描述】:

给定下面的代码

char buf[] = "asfsf";

char *a=buf;
++*a++;
cout<<*a;

我希望结果是“s”的下一个字符,即“t”,但结果仍然是“s”。为什么?

为什么 ++*a++ 和

不一样
*a++;
++*a;
cout<<*a;

这真的是 ++i++ 的重复问题吗?我知道 ++i++ 是一种未定义的行为,会导致编译错误,但 ++*i++ 实际上可以运行。我的情况也是未定义的行为吗?

【问题讨论】:

你应该使用const char *a="asfsf"; 不是一个骗子(至少是指定的副本)。这一个包括取消引用,这意味着两个增量应用于不同的对象(即,一个应用于a,另一个应用于*a)。这使得它与对同一个对象应用两个增量略有不同(但完全不同)。 你的代码应该被避免,即使它是明确定义的行为(不是)。它在我的系统(OS X)上出现Bus error: 10 故障(以及从字符串常量到char* 的不推荐转换的警告) @vsoftco 它出错了,因为他正在写入只读内存(字符串文字)。 little modification 可能会在没有 ro-overreach 的情况下给出他所看到的内容.. @WhozCraig 同意,我使用的最大值仍然是 *a++。不止一个 2 ++/* 运算符只会让阅读您的代码的人感到困惑。 【参考方案1】:

根据语言语法,运算符关联为:

++(*a++)

注意:关联性并不意味着操作的顺序。

*a++ 计算为一个左值,指定a 最初指向的位置,具有修改a 的副作用。到目前为止一切都很好。

将前缀-++ 应用于该左值会增加存储在那里的值(将'a' 更改为'b')。

虽然这两个增量是无序的,但这不会导致UB,因为不同的对象在增量,并且指定后一个位置的左值不依赖于增量。 (它使用旧值a)。

【讨论】:

@bogdan 感谢您指出这一点。选项是 ++ cast-expressionpostfix-expression ++ 。但前者不会产生postfix-expression,而后者会产生cast-expression【参考方案2】:

就目前而言,您的代码具有未定义的行为,因为它试图修改字符串文字的内容。

阻止编译器接受此类代码的一种方法(可能是首选方法)是定义您的a,例如:

char const *a="asfsf";

这样,++*a 部分根本无法编译。

为了方便说明,我们稍微修改一下代码,变成:

#include <iostream>

int main() 

    char x[]="asfsf";
    char *a = x;
    ++*a++;
    std::cout<<x;

现在a 指向我们可以实际写入的内存,并获得有意义的结果。这将打印出bsfsf。如果我们打印出a,我们将得到sfsf

发生的情况是a++ 增加了a 仍然产生a 的原始值。即取消引用,引用x 的第一个元素。然后对其应用预增量,将其从 a 更改为 b

如果你想增加指针,取消引用结果,然后增加它,你可以使用:++*++a;。好吧,不,你不会使用它——或者至少我希望你不会。它确实增加了a 以指向数组的第二个元素,然后增加第二个元素以将其从s 更改为t——但是任何阅读代码的人都会被完全原谅,如果他们讨厌你的写作就这样吧。

【讨论】:

这对我来说很有意义。谢谢! 您能否详细说明为什么“a++ 增加了a 但仍然产生a 的原始值”?? @Martund:这就是定义后增量要做的事情。例如,如果我执行以下操作: int i=0; printf("%d", i++); printf("%d", i);, it should print out 0 1. So the i++`产生了i的现有值(即0),但增加了i,所以下次我们看它时,它值为 1。

以上是关于一起在指针上使用前缀和后缀时的奇怪输出的主要内容,如果未能解决你的问题,请参考以下文章

在 C 中对于后缀和前缀运算符,操作数应该是一个左值,那么在这些运算符的情况下,左值对于指针变量的实际含义是啥?

线性结构(链表栈和队列中缀前缀后缀表达式转换)

关于字符串 “*****AB**C*D*****” 中前缀后缀和中间 '*' 的处理

最长公共后缀-前缀

Textarea ng-bind,其中 value 有前缀和后缀

前缀和非前缀命令在 python discord bot 上不能一起工作