Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.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
字符*str=”之间的差异;“字符串”;和char str[]=";字符串“;?_C_Arrays_String_Pointers_Stack - Fatal编程技术网

字符*str=”之间的差异;“字符串”;和char str[]=";字符串“;?

字符*str=”之间的差异;“字符串”;和char str[]=";字符串“;?,c,arrays,string,pointers,stack,C,Arrays,String,Pointers,Stack,在编写一个简单函数以从字符串中删除特定字符时,我遇到了一个奇怪的问题: void str_remove_chars( char *str, char to_remove) { if(str && to_remove) { char *ptr = str; char *cur = str; while(*ptr != '\0') { if(*ptr != to_remove)

在编写一个简单函数以从字符串中删除特定字符时,我遇到了一个奇怪的问题:

void str_remove_chars( char *str, char to_remove)
{
    if(str && to_remove)
    {
       char *ptr = str;
       char *cur = str;
       while(*ptr != '\0')
       {
           if(*ptr != to_remove)
           {
               if(ptr != cur)
               {
                   cur[0] = ptr[0];
               }
               cur++;
           }
           ptr++;
       }
       cur[0] = '\0';
    }
}
int main()
{
    setbuf(stdout, NULL);
    {
        char test[] = "string test"; // stack allocation?
        printf("Test: %s\n", test);
        str_remove_chars(test, ' '); // works
        printf("After: %s\n",test);
    }
    {
        char *test = "string test";  // non-writable?
        printf("Test: %s\n", test);
        str_remove_chars(test, ' '); // crash!!
        printf("After: %s\n",test);
    }

    return 0;
}
我不明白为什么第二次测试失败了? 在我看来,它就像第一个符号
char*ptr=“string”
相当于这个:
charptr[]=“string”


不是吗?

严格地说,
char*ptr
的声明只保证指向字符类型的指针。字符串构成已编译应用程序的代码段的一部分并不罕见,某些操作系统会将其设置为只读。问题在于,您正在假设预定义字符串的性质(即它是可写的),而事实上,您自己从未为该字符串显式创建内存。编译器和操作系统的某些实现可能会允许您执行您尝试执行的操作


另一方面,根据定义,
char test[]
的声明实际上为堆栈上的整个字符数组分配可读写内存。

这两个声明不同

char ptr[]=“字符串”
声明大小为
7
的字符数组,并使用字符
s
t
r
i
n
g
\0
对其进行初始化。允许您修改此数组的内容

char*ptr=“string”
ptr
声明为字符指针,并使用只读的字符串literal
地址“string”
对其进行初始化。修改字符串文字是一种未定义的行为。您所看到的(seg故障)是未定义行为的一种表现。

据我记忆所及

char ptr[] = "string";
在堆栈上创建
“string”
副本,因此此副本是可变的

形式

char *ptr = "string";
只是向后兼容

const char *ptr = "string";
而且你不允许(就未定义的行为而言)修改它的内容。
编译器可以将这些字符串放在内存的只读部分。

char*test=“string test”
错误,它应该是
const char*
。这段代码编译只是因为向后兼容的原因。
const char*
所指向的内存是只读内存,无论何时尝试写入,它都会调用未定义的行为。另一方面,
chartest[]=“string test”
在堆栈上创建一个可写字符数组。这与您可以写入的任何其他常规局部变量一样。

回答得好@codaddict

另外,
sizeof(ptr)
将为不同的声明提供不同的结果

第一个是数组声明,它将返回数组的长度,包括终止的空字符

第二个,
char*ptr=“长文本…”
将返回指针的长度,通常为4或8

char *str = strdup("test");
str[0] = 'r';

是正确的代码并创建可变字符串。str在堆中被分配了一个内存,值“test”填入其中。

和sizeof(ptr)对于不同的声明也会给出不同的结果。第一个将返回数组的长度,包括终止的空字符。第二个将返回指针的长度,通常为4或8。第二个位置也可以更改ptr的内容。但是内容是指向文字的指针,而不是字符。+1,很好的答案。了解
char*ptr=“string”ptr可以指向其他对象,因此可以在指向的内容中进行“更改”,但是字符
“string”
是一个文本,不能更改。性能问题也值得一提。每次变量进入作用域时,声明初始化的自动数组变量将填充整个数组内容。当变量进入作用域时,声明初始化的自动指针变量只需分配指针(单字写入)。如果字符串很长或者经常输入块(就像循环的每次迭代),那么差异可能非常显著@实际上,
sizeof(ptr)
不是数组的长度,除非
ptr
声明为字符数组。如果
ptr
被定义为一个包含3个元素的整数数组,
sizeof(ptr)
将返回每个元素的
sizeof(int)
之和。我不会说这是错误的。您可能希望以后让
test
指向一个可修改的字符串,并保留一个标志(在另一个变量中),指示是否已将其替换为可修改的内容。尽管如此,在大多数情况下,使用
const
there.Hem可能是一种很好的做法。因此,每次执行该函数时,都会分配5个字节?关于此主题的非常好的文章:阅读: