C:字符串、数组和指针?阵列故障?

C: String, Array and Pointer? Array failure?

我想知道是否可以在不更改地址的情况下更改存储在变量中的字符串。 而且我无法编写代码来执行此操作,因为当我编写

这样的代码时
char* A = "abc";
char* B = "def";
A = B; <-- if I write down this code, then A will point to B and address changes. 

那么有谁知道如何做到这一点,将存储在A中的字符串更改为"def",而不更改A的初始地址?

此外,我再次尝试只更改变量 A 中的一个字,而不更改地址。

为此,我编写了以下失败代码。但我不知道为什么会失败。

#include <stdio.h>
#include <string.h>

int main(void)
{
    char* s = "ABC";

    // print value and address of s.
    printf("Value of s is %s \n", s);
    printf("Address of s is %p \n", s);

    s[0] = 'v';

    printf("Value of s is %s \n", s);
    printf("Address of s is %p \n", s);
}

使用 gdb,我发现 s[0] = 'v' 无效并导致分段错误。为什么会这样?谁也能告诉我这背后的原因吗? 谢谢。

只有当内容驻留在 "writable" 内存中时,您才能更改字符串。当你这样做时

char* A = "abc";

字符串A的内容,一个字符串文字,驻留在内存中,无法写入。但是,如果您将声明更改为 this

char A[] = "abc";

您的字符串将变得可写,并且您可以将新内容复制到其中:

char A[] = "abc";
char* B = "def";
strcpy(A, B);

字符串的地址将保持不变。

这里需要注意的是,如果字符串内容比原始字符串长,则不能将其复制到 A 中。要解决此问题,请声明具有特定大小的 A,如下所示:

char A[100] = "abc";
char* B = "quick brown fox jumps over the lazy dog";
strcpy(A, B); // This would work fine

This answer is based on a similar one of mine from some time ago.

通过以您的方式声明一个字符串,您已经有效地创建了一个 const 存储在只读内存中的字符串。

简答:


char A[] = "abc";  // 'A' points to a read-write string, which is 4 characters long { 'a', 'b', 'c', '[=10=]' }
char* B;           // 'B' is a pointer that currently points to an unknown area since it isn't initialized
B = A;             // 'A' and 'B' now point to the same chunk of memory
char C[] = "abc";
snprintf(C, strlen(C)+1, "def"); // Modify the contents of the area 'C' points to, but don't change what 'C' actually points to.

长答案:


考虑下面的例子:

char strGlobal[10] = "Global";

int main(void) {
  char* str = "Stack";
  char* st2 = "NewStack";
  str = str2;  // OK
  strcpy(str, str2); // Will crash
}

为了安全起见,您实际上应该分配为指向 const 数据的指针,以确保您不会尝试修改数据。

const char* str = "Stack"; // Same effect as char* str, but the compiler
                           // now provides additional warnings against doing something dangerous

第一种分配内存的方法是只读内存中的静态分配(即:与strstr2一样)。

第二种分配称为动态分配,它在堆上而不是堆栈上分配内存。可以毫不费力地修改字符串。在某些时候,您需要通过 free() 命令释放这个动态分配的内存。

还有第三种分配字符串的方法,就是在栈上静态分配。这允许您修改保存字符串的数组的内容,并且它是静态分配的。

char str[] = "Stack";

总结:

Example:                       Allocation Type:     Read/Write:    Storage Location:
================================================================================
const char* str = "Stack";     Static               Read-only      Code segment
char* str = "Stack";           Static               Read-only      Code segment
char* str = malloc(...);       Dynamic              Read-write     Heap
char str[] = "Stack";          Static               Read-write     Stack
char strGlobal[10] = "Global"; Static               Read-write     Data Segment (R/W)