在 C 中,可以使用字符指针或字符数组来引用字符串。
字符串作为字符数组
当字符串被声明为字符数组时,它们的存储方式与 C 中其他类型的数组一样。例如,如果 str[] 是自动变量,则字符串存储在堆栈段中,如果是全局变量或静态变量,则存储在数据段中, 等等。
使用字符指针字符串
使用字符指针字符串可以存储在两个方面:
1)共享段中的只读字符串。
当字符串值直接分配给指针时,在大多数编译器中,它存储在函数之间共享的只读块中(通常在数据段中)。
在上述行中,“GfG”存储在共享只读位置,但指针 str 存储在读写存储器中。您可以将 str 更改为指向其他内容,但目前无法更改 str 的值。所以这种字符串应该只在我们不想在程序后期修改字符串时使用。
2)在堆段中动态分配。
字符串像 C 中其他动态分配的东西一样存储,并且可以在函数之间共享。
让我们看一些例子来更好地理解上述存储字符串的方法。
示例 1(尝试修改字符串)
下面的程序可能会崩溃(给出分段错误错误),因为 *(str+1) = 'n' 行尝试写入只读内存。
下面的程序运行良好,因为 str[] 存储在可写堆栈段中。
下面的程序也可以正常工作,因为 str 处的数据存储在可写堆段中。
示例 2(尝试从函数返回字符串)
下面的程序工作得非常好,因为字符串存储在共享段中,即使在 getString() 返回后,存储的数据仍保留在那里
下面的程序也可以很好地工作,因为字符串存储在堆段中,并且即使在 getString() 返回后,存储在堆段中的数据仍然存在
但是,下面的程序可能会打印一些垃圾数据,因为字符串存储在函数 getString() 的堆栈帧中,并且 getString() 返回后数据可能不存在。
char str[4] = "GfG"; /*One extra for string terminator*/
/* OR */
char str[4] = {‘G’, ‘f’, ‘G’, ' '}; /* ' ' is string terminator */
char *str = "GfG";
char *str;
int size = 4; /*one extra for ‘ ’*/
str = (char *)malloc(sizeof(char)*size);
*(str+0) = 'G';
*(str+1) = 'f';
*(str+2) = 'G';
*(str+3) = ' ';
int main()
{
char *str;
str = "GfG"; /* Stored in read only part of data segment */
*(str+1) = 'n'; /* Problem: trying to modify read only memory */
getchar();
return 0;
}
int main()
{
char str[] = "GfG"; /* Stored in stack segment like other auto variables */
*(str+1) = 'n'; /* No problem: String is now GnG */
getchar();
return 0;
}
int main()
{
int size = 4;
/* Stored in heap segment like other dynamically allocated things */
char *str = (char *)malloc(sizeof(char)*size);
*(str+0) = 'G';
*(str+1) = 'f';
*(str+2) = 'G';
*(str+3) = ' ';
*(str+1) = 'n'; /* No problem: String is now GnG */
getchar();
return 0;
}
char *getString()
{
char *str = "GfG"; /* Stored in read only part of shared segment */
/* No problem: remains at address str after getString() returns*/
return str;
}
int main()
{
printf("%s", getString());
getchar();
return 0;
}
char *getString()
{
int size = 4;
char *str = (char *)malloc(sizeof(char)*size); /*Stored in heap segment*/
*(str+0) = 'G';
*(str+1) = 'f';
*(str+2) = 'G';
*(str+3) = ' ';
/* No problem: string remains at str after getString() returns */
return str;
}
int main()
{
printf("%s", getString());
getchar();
return 0;
}
char *getString()
{
char str[] = "GfG"; /* Stored in stack segment */
/* Problem: string may not be present after getString() returns */
/* Problem can be solved if write static before char, i.e. static char str[] = "GfG";*/
return str;
}
int main()
{
printf("%s", getString());
getchar();
return 0;
}