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++;
}
}
第一个程序工作得很好,但是其他的分段错误,那么,如果需要编辑字符串,是否必须只传递在函数之间使用数组初始化的字符串常量?
答案 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编译器合并相同文字的存储,或者是其他文字后缀的文字。
a
和b
是否紧密相关无关紧要;这种偷偷摸摸的效果甚至可能发生在不同功能的远程声明之间,甚至可能发生在不同的翻译单元中。
字符串文字应该被视为程序图像的一部分;成功修改字符串文字的程序实际上是自修改代码。您在环境中遇到“分段错误”的原因正是因为防止自修改代码:编译程序的“文本”部分(包含机器代码)位于虚拟内存的写保护页面中。字符串文字与机器代码一起放在那里(通常散布在它的功能中)。尝试修改字符串文字导致对文本部分的写访问,这些访问被页面上的权限位阻止。
在另一种环境中,C代码可能用于生成进入只读存储器的软件映像:实际ROM芯片。字符串文字与代码一起进入ROM。尝试修改一个会增加尝试修改ROM。硬件可能没有检测到。例如,该指令可能似乎执行,但是当回读该位置时,原始值仍然存在,而不是新值。与分段错误一样,这属于“未定义行为”的规范范围:任何行为都是!