C中的数组字符串和公共数组有什么不同?

JIN*_*U_K 5 c memory arrays string pointers

#include<stdio.h>
int main()
{
    char str[7];
    scanf("%s",&str);

    for(i=0; i<7; i++)
    {
        printf("%x(%d) : %c\n",&str[i], &str[i], str[i]);
    }

    printf("\n\n%x(%d) : %c      or    %s",&str, &str, str, str);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

由于Array with String,我对C数组的指针感到困惑.

实际上我想为单行输入保存每个字符.

它有用,但我发现了一些奇怪的东西......

主要问题是&str&str [0]具有相同的地址值.

str的字符串值为%s ..

str [0]的 Char 值为%c ..

我使用str和%c然后它有前两个str的地址.

Array中发生了什么?

Stirng值的真实地址在哪里?

以及如何可以SCANF("%S",&STR)分发的字符串各字符数组空间?

Input : 123456789
62fe40(6487616) : 1
62fe41(6487617) : 2
62fe42(6487618) : 3
62fe43(6487619) : 4
62fe44(6487620) : 5
62fe45(6487621) : 6
62fe46(6487622) : 7

62fe40(6487616) : @    123456789
Run Code Online (Sandbox Code Playgroud)

这是我的代码的结果窗口.

Eri*_*hil 1

\n

C语言中字符串数组和普通数组有什么不同?

\n
\n\n

数组是一种类型的对象的连续序列。1

\n\n

字符串是由第一个空字符终止的连续字符序列。2因此,字符串只是一个字符数组,我们通过放置一个值为零的字符来标记结束。(通常,字符串临时保存在较大的数组中,这些数组在空字符后具有更多元素。)

\n\n

所以每个字符串都是一个数组。字符串只是一个具有两个额外属性的数组:它的元素是字符,零标记结束。

\n\n
\n

&str&str[0]具有相同的地址值。

\n
\n\n

&str是数组的地址。&str[0]是第一个元素的地址。

\n\n

这些是内存中的同一位置,因为第一个元素与数组的起始位置相同。因此,当您打印或检查它们时,它们通常看起来是相同的。(地址可以有不同的表示形式,就像您可以编写 \xe2\x80\x9c200\xe2\x80\x9d 或 \xe2\x80\x9ctwo Hundred\xe2\x80\x9d 或 \xe2\x80\x9c2\xe2\x80 \xa210 2 \xe2\x80\x9d 表示相同的数字。因此,相同的地址有时可能看起来不同。在大多数现代系统中,地址只是内存中某个位置的简单数字,您不会看到差异。但它可以发生。)

\n\n
\n

printf("%x(%d) : %c\\n",&str[i], &str[i], str[i]);

\n
\n\n

这不是打印地址的正确方法。要正确打印地址,请将其转换为void *并使用%p3

\n\n
printf("%p(%p) : %c\\n", (void *) &str[i], (void *) &str[i], str[i]);\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

printf("\\n\\n%x(%d) : %c or %s",&str, &str, str, str);

\n\n

\xe2\x80\xa6

\n\n

我将str与 %c 一起使用,然后它具有str \ 地址的前两个数字。

\n
\n\n

上式中printf,第三个转换规范为%c,对应的参数为str%c旨在用于字符4 ,但您向其传递一个作为指针的参数。这里可能发生的情况是printf使用您传递给它的指针,就好像它是一个int. 然后可能会像使用字符一样printf使用其中的一部分并将其打印出来。int所以您看到地址的一部分显示为字符。然而,当你写\xe2\x80\x9cit时,有点不清楚str \的地址\xe2\x80\x9d的前两个数字。您可以显示确切的输出来澄清这一点。

\n\n

尽管printf可能已将指针用作int,但 C 标准并未定义其行为。传递错误的类型进行printf转换是不正确的,并且可能会发生其他结果,包括程序打印垃圾或崩溃。

\n\n
\n

scanf("%s",&str)如何将 String 分配到每个 char 数组空间?

\n
\n\n

str传递给scanffor的正确方法%s是传递第一个字符的地址&str[0]。C 对数组有一个特殊的规则,例如str:如果在表达式中使用数组而不是作为操作数sizeof或地址运算符&,则它将转换为指向其第一个元素的指针。5因此,您可以使用scanf("%s", str),它将与 相同scanf("%s", &str[0])

\n\n

但是,当您使用 时scanf("%s",&str),您传递的是数组的地址而不是第一个字符的地址。虽然这些是相同的位置,但它们是不同的类型。回想一下,指向同一地址的两种不同类型的指针可能具有不同的表示形式。因为scanf不知道您传递给它的实际参数类型,所以它必须依赖于转换说明符。%s告诉我们scanf期待一个指向字符的指针。6向其传递一个指向数组的指针是不正确的。

\n\n

C 有这个规则,因为有些机器有不同类型的指针,有些系统可能以不同的方式传递不同类型的指针。尽管如此,通常代码会通过&str而不是str按照作者期望的方式运行,因为 C 实现对两个指针使用相同的表示形式。因此scanf实际上可能会收到它工作所需的指针值%s7

\n\n

脚注

\n\n

1 C 2018 6.2.5 20。(这意味着该信息来自 2018 版 C 标准,ISO/IEC 9899,Information technology\xe2\x80\x94Programming Languages\xe2\x80\x94C,第 6.2.5 条,段落20.)

\n\n

2 C 2018 7.1.1 1. 请注意,终止空字符被视为字符串的一部分,尽管函数不计算它strlen

\n\n

3C 2018 7.21.6.1 8。

\n\n

4 从技术上讲,参数应该具有 type int,并将printf其转换为unsigned char具有该代码的字符并打印该字符。C 2018 7.21.6.1 8。

\n\n

5 C 2018 6.3.2.1 3. 用于初始化数组的字符串文字(如 中)char x[] = "Hello";也不会转换为指针。

\n\n

6 C 2018 7.21.6.2 12。

\n\n

7即使 C 实现对不同类型的指针使用相同的表示形式,也不能保证在需要另一种指针类型时使用一种指针类型能够工作。当编译器优化程序时,它依赖于程序\xe2\x80\x99的作者遵守规则,并且优化可能会以不会破坏遵循规则的程序但确实会破坏遵循规则的程序的方式改变程序。违反规则。

\n