找出错误或错误

你能找到以下代码的错误吗?

int main(){ char *p="hai friends",*p1; p1=p; while(*p!='\0') ++*p++; printf("%s %s",p,p1); } 

我预计它将打印空格后跟一个字符串!

这是一种使用++*p++

 #include  #include  int main(int argc, char* argv[]) { char *p = "My test string", p1[15]; strncpy(p1, p, 14); p1[14] = 0; p = p1; while (*p != 0) { printf("%c", ++*p++); } } 

请注意, p1是在堆栈上分配的内存数组(通常),而p是(通常)指向只读内存的指针,上面的代码移动到指向p1而不是(通常)只读位置驻留。 某些操作系统和/或编译器将表现出其他行为,但这是现代操作系统内置的一种保护机制,可以防止某些类别的病毒。

表达式++*p++ ; 相当于;

 ++*p; p++; 

++*p; 手段

 *p = *p + 1; 

因为postfix ++优先级高于取消引用运算符* ,所以它适用于*p

并且p指向一个常量字符串文字。 在上面的操作中,您试图“在只读内存上写入” – 这是非法的 – 因此错误。

建议:

首先 – 声明一个可以修改的数组,不能更改字符串文字。
声明(阅读评论):

 char string_array[] ="hai friends"; // notice `[]` in this declaration // that makes `string_array` array // to keep save original string do: char p1[20]; // sufficient length // notice here `p1` is not pointer. strcpy(p1, string_array) ; char *p = string_array; 

现在您可以修改指针pstring_array[]数组内容。

虽然Grijesh Chauhan的回答是正确的说法:

 ++*p++; 

 ++*p; p++; 

具有相同的效果,编译器不会将第一个表达式解释为像第二个表达式一样。 第一个表达式的括号版本是:

 ++(*(p++)); 

这意味着逻辑上 – 尽管编译器可以重新排序细节,只要结果是相同的 – p的后增量发生在结果被取消引用之前,并且预增量对原始值指向的数据进行操作。 p 。 让我们一步一步地完成:

  1. p++ – 返回p++的原始值并将p递增以指向下一个字符。
  2. *(p++) – 取消引用p的原始值。
  3. ++(*(p++) – 递增++(*(p++)的原始值指向的对象,并返回该对象的递增值。

因此,给定此代码(避免修改字符串文字 – 这是未定义的行为):

  #include  int main(void) { char array[] = "ayqm"; char *p = array; char c; c = ++*p++; printf("%c\n", c); printf("%s\n", array); // Print the string c = ++*p++; // Repeat the process printf("%c\n", c); printf("%s\n", array); return 0; } 

输出是:

 b byqm z bzqm 

这个答案中的任何内容都不应被解释为鼓励使用像++*p++那样复杂的表达式。 理解或维护C并不容易,因此它不好C.但是,它是合法的C.如果变量p指向初始化的可修改内存,则++*p++的行为是完全定义的。