c - 在C中,是否必须传递字符数组名称才能更改字符串常量的字符?

标签 c arrays string

C 中的字符串常量可以通过两种方式初始化:使用数组和字符指针;

两者都可以访问字符串常量并可以打印它;

来到编辑部分,如果我想编辑一个使用数组初始化的字符串,它很简单,我们可以使用数组单个字符进行编辑。

如果我想编辑一个使用字符指针初始化的字符串,这是不可能的吗?

让我们考虑以下两个程序:

程序#1:

#include<stdio.h>

void str_change(char *);

int main()
{
    char str[] = "abcdefghijklm";

    printf("%s\n", str);
    str_change(str);
    printf("%s\n", str);

    return 0;
}

void str_change(char *temp)
{
    int i = 0;

    while (temp[i] != '\0') {
    temp[i] = 'n' + temp[i] - 'a';
    i++;
}
}

程序#2:

#include<stdio.h>

void str_change(char *);

int main()
{
    char *str = "abcdefghijklm";

    printf("%s\n", str);
    str_change(str);
    printf("%s\n", str);

    return 0;
}

void str_change(char *temp)
{
    int i = 0;

    while (temp[i] != '\0') {
        temp[i] = 'n' + temp[i] - 'a';
        i++;
    }
}

我尝试使用以下版本的函数来编程 #2,但没有用

void str_change(char *temp)
{
        while (*temp != '\0') {
                *temp = 'n' + *temp - 'a';
                temp++;
        }
}

第一个程序运行良好,但其他程序出现段错误,那么,如果需要编辑字符串,是否必须仅在函数之间传递使用数组初始化的字符串常量?

最佳答案

So it is mandatory to pass only the string constants that are initialized using arrays between functions, if editing of string is requiredc?

基本上是的,尽管真正的解释并不是这些确切的文字。以下定义创建一个数组:

char str[] = "abc";

这不是字符串文字。 "abc" 标记是字符串文字语法,而不是字符串文字对象。在这里,该文字指定 str 数组的初始值。数组对象是可修改的。

char *str = "abc";

这里源代码中的“abc”语法是表示翻译后的程序镜像中的字符串文字对象的表达式。它也是一种数组,具有静态存储持续时间(与str的存储持续时间无关)。 "abc" 语法计算结果为指向该数组第一个字符的指针,并且 str 指针使用该指针值进行初始化。

字符串文字不需要支持修改;尝试修改字符串文字对象的行为是未定义的行为。

即使在无法预测段错误的系统中,也可能会发生奇怪的事情。例如:

char *a = "xabc";
char *b = "abc";

b[0] = 'b';  /* b changes to "bbc" */

假设作业有效。 a 也可能会更改为 "xbbc"。 C 编译器允许合并相同文字或作为其他文字后缀的文字的存储。

ab 是否靠近并不重要;即使在不同函数中的远程声明之间,甚至在不同的翻译单元中,这种偷偷摸摸的效果也可能发生。

字符串文字应被视为程序镜像的一部分;成功修改字符串文字的程序实际上是自修改代码。在您的环境中出现“段错误”的原因正是因为防止自修改代码:已编译程序的“文本”部分(包含机器代码)位于虚拟内存的写保护页中。字符串文字与机器代码一起放置在那里(通常散布在其函数中)。尝试修改字符串文字会导致对文本部分的写访问,该访问会被页面上的权限位阻止。

在另一种环境中,C 代码可能用于生成进入只读存储器的软件镜像:实际的 ROM 芯片。字符串文字与代码一起进入 ROM。尝试修改一个就相当于尝试修改 ROM。硬件可能无法检测到这一点。例如,指令可能看起来正在执行,但是当读回该位置时,原始值仍然存在,而不是新值。与段错误一样,这在“未定义行为”的规范范围内:任何行为都是!

关于c - 在C中,是否必须传递字符数组名称才能更改字符串常量的字符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45667274/

相关文章:

我可以使用 malloc 模拟 strcpy 吗?

c - 在 char 数组指针内赋值

c - 得到了正确的答案,但不知道如何或为什么。需要解释

java - 在框架中画一根绳子。

python - 如何从字符串中删除\n 双引号之间的发现?

c# - 是否有与 FoxPro 的 addbs() 等效的 C#?

c - 如何计算C中的执行时间?

c++对函数执行操作并声明函数

c - 程序按顺序忽略了一些函数

c - STM32F4 - 我可以在中断例程中使用延迟吗?