有关声明和初始化字符串以及字符串存储区域的查询

时间:2019-03-20 11:42:06

标签: c string pointers

我的问题分为三个部分。

char str[] = "hello!";
    char *str1 = "heello!";
    puts(str);
    str1[1] = 1
    puts(str1);
    printf("%s\n", str1);
    printf("%p\n", str1);

代码输出:

hello!
h1ello!
heello!
0x10735ef9b

1)我了解,当您声明一个char *类型时,就是在声明一个指向char类型的指针。通常对于指针,因为它包含其指向的变量的地址,所以当您打印指针本身时,您将获得存储在指针中的地址,并且只有在取消引用指针时,才可以获取存储的内容在指针所指向的变量中。 但是对于char *类型,为什么它不像常规指针那样起作用?您可以打印'char *'指针所指向的变量的内容而不用解引用,也可以通过更改str1 [1]的值来像字符串变量(而不是指针)一样使用它。 / p>

2)有人教我不要在指针主题中这样声明指针变量:

char *str1 = "heello!";

因为指针变量将指向当时内存中的任何地址,因此冒着更改您不想要的内存位置中的值并导致段错误的风险。 因此,您应该执行以下操作:

char *str1;
char c;
str1 = &c;
*addr = "hello!"

通过执行上述操作,在取消引用和写入该位置之前,请确保您的指针指向正确的位置。

但是在字符串的注释中,它声明要这样声明和初始化:

char *str1 = "heello!";

对于现在声明char *指针时应该遵循的内容,我感到很困惑。请帮忙。

3)在我的笔记中说,字符串的位置存储在内存的只读区域(称为文本区域)中。 因此,这样做:

    char *str1 = "hello!";
    str[1] = '.';

将使程序崩溃。

但是,当您这样做时:

char str2[7] = "hello!";
str2[1] = '.';

可以,并且可以成功地将字符串中的第二个元素从'e'更改为'。'

对此的解释是,str1指向内存中的只读区域,而str2包含堆栈中字符串的副本。 我不明白上述两种声明字符串变量的不同方式在执行代码时如何产生如此大的差异。请帮忙。

谢谢!

1 个答案:

答案 0 :(得分:3)

"heello!"这样的字符串文字实际上是只读个字符数组(包括字符串null终止符)。

使用

char *str1 = "heello!";

您使str1指向此类数组的第一个字符。

当您执行str1[1] = 1时,您尝试修改只读数组,该数组被禁止并导致undefined behavior可以但不必导致崩溃)。

这就是为什么您应该对字符串使用自己的数组,或者使用const char *指向文字字符串的原因。