c - 为什么我们可以读取这个分配的指针中的任何字符而不写入它?

标签 c arrays pointers

我还是C的新手

char* str = (char*)malloc(512);
str = "hello";
*(str) = 'H'; // Segmentation fault

我得到一个Segmentation fault在第三行尝试设置一个字符

我知道str是指向第一个 char指针我可以打印

printf("%c\n", *str); // Output: h

那么,它在只读内存中吗?我不确定为什么会发生这种情况,但我可以像我一样更改整个指针

str = "hello";

我能做到

char** str = (char**)malloc(512*sizeof(char*));
*str = "hello";
*(str+1) = "Yo!";
//*(str) = 'H';
printf("%s\n", *(str)); // Prints: hello
printf("%s\n", *(str+1)); // Prints: Yo!

从最后的代码来看,我可以做到这一点,而且仍然相同

str[0] = "hello";
str[1] = "Yo!";

原因是它毕竟是一个指针数组,我只是像第一个代码中那样更改指针,并使用一些索引

以及原因*(str+1) = "Yo!";有效,我正在增加char*地址或0索引这给了我下一个相邻 char* 的地址

从最后的代码来看,我不能做类似的事情

  **(str) = 'H';

*(str)[0] = 'H';

str[0][0] = 'H';

除非如果我有一个字符数组

char str[5][10]; // allocated 5 strings slots, 10 max characters for each
*(str)[0] = 'H';
*(str[0]+1) = 'e';
str[0][2] = 'l';
str[0][3] = 'l';
*((*str)+4 )= 'o';
printf("%s\n", str[0]); // Prints: Hello

我可以分配512 char 并只需使用 12 ,我可以分配1024 char 并且仍然需要更多,如果分配太多,我可能会内存不足

我必须使用 char* 并且我需要能够更改 an char 的值就像我在最后一个数组

中所做的那样

比如,假设我正在构建一个编译器、文本编辑器......
我需要能够在运行时分配内存并检查一些字符,例如 ';'

split()函数,它分割 char*到一个指针数组

  • 开始复制 char[s]进入char[n][i] // n = 0, ++i, ++s
  • 对于每个 ';' char*中的迭代, i = 0, ++n
  • 返回char**

如果我使用二维数组,这可以很容易地完成,但它们不是,它们是指针......

我们如何更改 char 的值在这个指针中?

为什么我们可以阅读任何char在此指针中而不写入它?

我还没有完全理解指针,如果代码有问题,抱歉,谢谢。

最佳答案

这里出现段错误

char* str = (char*)malloc(512);
str = "hello";
*(str) = 'H'; // Segmentation fault

因为您将 ptr 设置为指向字符串文字,即旧值 (由 malloc 返回)消失了。修改字符串文字是未定义的行为 在大多数系统中,字符串文字无论如何都在只读存储器中,所以你不能 修改它们。段错误就是其结果。

请注意,str = "hello" 是一个赋值,您正在复制 where 的地址 字符串文字存储在内存中的指针 str 中。 str 现在是 指向字符串文字。 但是您还没有复制 contents,为此您需要使用 strcpystrncpy 等函数:

char* str = malloc(512);
if(str == NULL)
{
    // error handling
    // do not continue
}
strcpy(str, "hello"); // copying the content of the string literal
*(str) = 'H'; // now it works

请注意 you don't have to cast malloc 。并且不要忘记 检查 malloc 是否返回 NULL 并随后释放内存。

编辑

   char str[5][10]; // allocated 5 strings slots, 10 max characters for each
   *(str)[0] = 'H';
   *(str[0]+1) = 'e';
   str[0][2] = 'l';
   str[0][3] = 'l';
   *((*str)+4 )= 'o';
   printf("%s\n", str[0]); // Prints: Hello

这里有一个问题,你没有设置'\0'-终止 byte,printf 产生未定义的行为。正确的代码应该是:

char str[5][10]; // allocated 5 strings slots, 10 max characters for each
*(str)[0] = 'H';
*(str[0]+1) = 'e';
str[0][2] = 'l';
str[0][3] = 'l';
*((*str)+4 )= 'o';
str[0][5] = '\0'; // terminating the string
printf("%s\n", str[0]); // Prints: Hello
<小时/>

编辑2

How can we change the value of an char in a pointer in C?

您困惑的问题是您没有意识到您丢失了 指向已分配内存块的指针并尝试修改字符串文字 相反。

如何更改指针中 char 的值?

像这样:

char text[] = "This is a long text";
char *ptr = text;
ptr[0] = 't';

这有效,因为 text 已使用字符串的内容进行初始化 文字。 ptr 指向字符序列的开始位置 存储在 text 中,ptr[0] 允许您访问中的第一个字符 序列。

Why can we read any char in an pointer and not write to it?

如果您没有权限(例如只读内存)或 指针被声明为const,那么你显然不能写一个字符 通过指针。但如果指针指向有效的、可写的内存,那么 您可以通过指针书写字符。

关于c - 为什么我们可以读取这个分配的指针中的任何字符而不写入它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49100220/

相关文章:

c - 是什么导致了这些默认数组值?

c - 以下代码中的表达式语法错误

php - 如何将多维数组放入双引号字符串?

c++ - 我什么时候使用哪种指针?

c++ - 使用 WriteProcessMemory 和指针写入另一个进程的内存

c - 二维数组总是需要循环分配吗?

c - 指向 C 中结构指针的空指针

java - 使用 While 与 If 防止数组中出现重复的整数 ID 号

python - NumPy 的内存效率

c - 如何将此结构放入动态分配的空间中?