char * str =“STRING”和char str [] =“STRING”之间的区别?

时间:2010-10-05 10:37:30

标签: 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)
           {
               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";看起来与此相同:char ptr[] = "string";

不是这样吗?

6 个答案:

答案 0 :(得分:40)

两个声明不一样。

char ptr[] = "string";声明一个大小为7的字符数组,并使用字符为str,{{1}对其进行初始化},ing。您允许修改此数组的内容。

\0char *ptr = "string";声明为char指针,并使用字符串文字 ptr的地址对其进行初始化,只读 。修改字符串文字是未定义的行为。你所看到的(seg fault)是未定义行为的一种表现形式。

答案 1 :(得分:5)

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

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

答案 2 :(得分:3)

char *test = "string test";错了,应该是const char*。此代码仅因后向兼容性原因而编译。 const char*指向的内存是只读内存,每当您尝试写入内存时,它都会调用未定义的行为。另一方面,char test[] = "string test"在堆栈上创建可写字符数组。这与您可以编写的任何其他regualr局部变量一样。

答案 3 :(得分:2)

据我记得

char ptr[] = "string";

在堆栈上创建"string"副本,因此这个是可变的。

表格

char *ptr = "string";

只是

的向后兼容性
const char *ptr = "string";

并且不允许(在未定义的行为方面)修改其内容。 编译器可以将这些字符串放在内存的只读段中。

答案 4 :(得分:0)

好的答案@codaddict。

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

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

第二个,char* ptr = "a long text...";将返回指针的长度,通常为4或8。

答案 5 :(得分:0)

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

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