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

时间:2017-08-14 03:59:27

标签: 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++;
        }
}

第一个程序工作得很好,但是其他的分段错误,那么,如果需要编辑字符串,是否必须只传递在函数之间使用数组初始化的字符串常量?

3 个答案:

答案 0 :(得分:0)

字符串文字存储在静态持续时间存储中,该存储在程序生存期内存在,并且可以是只读。更改此文字的内容会导致未定义的行为。

将此文字复制到可修改数组并将其传递给函数。

char array[5];
strcpy(array, "test");

如果要声明指向字符串文字的指针,请将其设为const,以便编译器在您尝试修改它时会发出警告。

const char * ptr = " string literal";

答案 1 :(得分:0)

我认为,因为如果你使用指针,你只能读取这个数组,你不能用循环写任何东西,因为你的数组元素几乎没有。 (抱歉我的英文)

答案 2 :(得分:0)

  

因此,如果需要编辑字符串,则必须仅传递在函数之间使用数组初始化的字符串常量?

基本上,是的,虽然真正的解释不是这些确切的词。以下定义创建一个数组:

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​​。硬件可能没有检测到。例如,该指令可能似乎执行,但是当回读该位置时,原始值仍然存在,而不是新值。与分段错误一样,这属于“未定义行为”的规范范围:任何行为都是!