C 关于运算符优先级的澄清

C 关于运算符优先级的澄清,c,operator-precedence,C,Operator Precedence,我从一些练习和问题中得到了这个片段:以下代码的输出是什么: main() { char *p = "ayqm"; printf("%c", ++*(p++)); } 我的预期答案是z,但实际答案实际上是b。这怎么可能 稍后编辑:代码段是从一个练习中提取的,它没有关注printf代码区域以外存在的字符串文字或语法问题。您的程序有未定义的行为,因为它试图修改字符串文字ayqm。根据标准,试图修改字符串文字会导致未定义的行为,因为它可能存储在只读存储器中 指针p指向字符串文字ayqm

我从一些练习和问题中得到了这个片段:以下代码的输出是什么:

main()
{
    char *p = "ayqm";
    printf("%c", ++*(p++));
}
我的预期答案是z,但实际答案实际上是b。这怎么可能


稍后编辑:代码段是从一个练习中提取的,它没有关注printf代码区域以外存在的字符串文字或语法问题。

您的程序有未定义的行为,因为它试图修改字符串文字ayqm。根据标准,试图修改字符串文字会导致未定义的行为,因为它可能存储在只读存储器中

指针p指向字符串文字ayqm。这句话

printf ("%c", ++*(p++));
最后尝试修改指针p指向的字符串文字


程序中未定义的行为包括:它可能会错误地执行,崩溃或无声地生成错误的结果,或者它可能会意外地完全按照程序员的意图执行。

如前所述,程序存在多个问题:

它试图修改字符串常量ayqm,这在C标准中被描述为未定义的行为。 它在没有正确声明的情况下使用printf,再次产生未定义的行为。 其输出未以换行符终止,导致实现定义的行为。 没有返回类型的main原型已经过时,不再受C标准支持。 递增字符产生实现定义的行为。如果执行字符集是ASCII,“a”+1产生“b”,但C标准不保证。事实上,在旧的大型计算机中仍然使用的EBCDIC字符集中,字母是单一的单调序列,即:“a”+1==“b”,但“i”+1!=”j'在这个字符集中。 以下是更正的版本:

#include <stdio.h>

int main(void) {
    char str[] = "ayqm";
    char *p = str;
    printf("%c\n", ++*(p++));
    return 0;
}
p是后递增的,这意味着p的当前值用于*运算符,p的值在下一个序列点(即调用printf函数)之前递增。然后,通过p‘a’读取的字符将递增,这可能产生也可能不产生‘b’,这取决于执行字符集


printf返回主函数后,p指向str[1],str包含字符串byqm。

将指针移动到包含“y”的地址,为什么?因为这将有助于确定问题的答案应该关注什么。您的响应告诉我们您缺少一些信息,现在我们知道了它是什么。但不幸的是,您的代码仍然存在问题,因为您正在修改字符串文字。该行为未定义。如果您愿意,我可以修复这个示例,这样它就不会使问题脱轨。p++增加p,但具有前面的p值,该值指向ayqm中的a。*运算符取消对指针的引用,给出值“a”。然后,++运算符将其递增,给出“a”+1的结果,即“b”。但请注意,ayqm是一个常量字符串,尝试像此代码那样修改它是一个错误。在某些系统上,如果常量字符串位于只读内存中,则会产生分段错误。我认为,与搜索我缺少的信息不同,您可以编写一行带提示的响应,就像许多其他系统一样。谢谢,这正是我要找的;postfx increment的关联性对我来说是一个问题:代码不是用来工作的,我想它只是这里感兴趣的priintf行。@TeodorPetrut:这是运算符优先级的问题,而不是关联性的问题。一元运算符的规则很简单:首先是posfix运算符,从左到右从最接近操作数的一个开始,然后前缀运算符也从最接近操作数的一个开始,因此从右到左。前缀递增的结果是递增的值,而后缀递增的结果是先前的值。递增对象的副作用发生在下一个序列点之前的未指定时间。@TeodorPetrut:关联性决定了二进制运算符的操作顺序。例如:*和/具有相同的优先级和从左到右的关联性,因此a/b*c被解析和计算为a/b*c,而=具有从右到左的关联性,因此a=b=c被解析为a=b=c。根据b的类型,a在a=c中可能得到不同的值。