Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 找出错误_C_Pointers - Fatal编程技术网

C 找出错误

C 找出错误,c,pointers,C,Pointers,您能找到以下代码的错误吗 int main(){ char *p="hai friends",*p1; p1=p; while(*p!='\0') ++*p++; printf("%s %s",p,p1); } 我以为它会打印空格后跟一个字符串 表达式+++*p++;相当于 ++*p; p++; ++*p;意味着 因为postfix++的优先级高于解引用操作符*,所以它应用于*p p指向一个常量字符串文字。在上面的操作中,您试图在只读内存上写入-这是非法的-

您能找到以下代码的错误吗

int main(){
    char *p="hai friends",*p1;
    p1=p;
    while(*p!='\0') ++*p++;
    printf("%s %s",p,p1);
}
我以为它会打印空格后跟一个字符串

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

++*p; 
p++;
++*p;意味着

因为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;
现在可以修改指针p和字符串_数组[]数组内容

这里有一种使用+++*p++的方法:

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

尽管by的说法是正确的:

++*p++;

同样,编译器不会像解释第二个表达式那样解释第一个表达式。第一个表达式的括号版本为:

++(*(p++));
这意味着逻辑上——尽管编译器可以在结果相同的情况下对细节重新排序——p的后增量出现在结果被取消引用之前,并且预增量对原始值p指向的数据进行操作。让我们一步一步地看一遍:

p++-返回p的原始值并递增p以指向下一个字符。 *p++-取消对p的原始值的引用。 ++*p++-将指向的对象按原始值p递增,并返回该对象的递增值。 因此,给定避免修改字符串文字的代码-这是未定义的行为:

    #include <stdio.h>

    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;
    }

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

那么它打印了什么?毫不奇怪……它对我来说是错误的:因此,字符串在C中是不可变的,一旦定义,我们就不能更改它们,,对???@cpp你不能修改常量字符串,你可以修改数组stringchar[N],等等,我在回答中建议你这么做。@cpp明白了吗?错误和建议。@JonathanLeffler是的,在阅读了你的答案后明白了你的意思!因此,当我们分配一个字符指针,一个字符串,字符串被写入内存,指针被返回并存储,内存区域是只读的,但是当我们声明一个字符数组时,一个可修改的内存区域被分配..对吗?thanx,这是一个很好的帮助1声明和strncpy是一种扭曲的写入方式:char p1[]=我的测试字符串;char*p=p1;。此外,p1不是“动态分配”的;这个术语是为malloc等人分配的内存保留的,它是可修改的内存;它是自动分配存储类自动;它不是动态分配的。有趣的是,C标准不包含“动态”一词,因此我的评论应该被理解为大多数谈论内存分配的人期望通过malloc等人在C中动态分配内存。如果p1是动态分配的,p、argc和argv也是如此。@jonathanleffler谢谢你指出这一点,我已经忘了如何正确使用术语。我已经更正了我的帖子。
++*p;
p++;
++(*(p++));
    #include <stdio.h>

    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