C中的String数组和common数组有什么区别?

时间:2019-02-23 10:16:22

标签: c arrays string pointers memory

#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;
}

由于带有String的数组,我对C Array的指针感到困惑。

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

这是可行的,但是我发现了一些奇怪的东西...

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

但是 str 具有%s的字符串值。

str [0] 具有%c的字符值。

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

Array中发生了什么。。

Stirng值的真实地址在哪里?

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

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

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

3 个答案:

答案 0 :(得分:2)

您很困惑,因为字符串和数组是同一件事。 -内存中只有数据(以及指向该数据的指针)

为字符串分配整数或缓冲区时,会保留一些内存。 c中的字符串定义为一个字节序列,该字节序列以一个字节终止,值为0-长度未知。使用定长数组,您可以使用已知的大小。

字符串的实际值是第一个字符的指针。

当用%c打印时,它期望一个字符-str [0]而不是指针-当用%s打印时,它期望一个指向字符序列的指针。

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

答案 1 :(得分:1)

  

C中的String数组和common数组有什么区别?

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

一个 string 是一个连续的字符序列,以第一个空字符结尾。 2 因此,字符串只是一个字符数组,在其中我们将一个值为零的字符。 (通常,字符串临时保存在较大的数组中,该数组在空字符之后包含更多元素。)

所以每个字符串都是一个数组。字符串只是具有两个额外属性的数组:其元素是字符,而零则表示结尾。

  

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

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

它们在内存中的位置相同,因为第一个元素从数组的位置开始。因此,当您打印或检查它们时,它们通常会看起来相同。 (地址可以具有不同的表示形式,以相同的方式可以为相同的数字写“ 200”或“ 200”或“ 2•10 2 ”。因此,相同的地址有时看起来可能会有所不同。在大多数现代系统中,地址只是内存中某个位置的简单数字,您不会看到任何差异。但这可能发生。)

  

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

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

printf("%p(%p) : %c\n", (void *) &str[i], (void *) &str[i], str[i]);
  

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

     

...

     

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

在上面的printf中,第三个转换规范为%c,相应的自变量为str%c用于字符 4 ,但是您要向其传递作为指针的参数。这里可能发生的情况是,printf使用了您传递的指针,就好像它是int一样。然后printf可能已经使用了int的一部分,就好像它是一个字符并打印出来一样。因此,您看到了部分地址显示为字符。但是,当您输入“它具有 str 的地址的前两个数字”时,尚不清楚。您可以显示确切的输出来澄清这一点。

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

  

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

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

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

C具有此规则,因为某些计算机具有不同类型的指针,并且某些系统可能以不同方式传递不同类型的指针。尽管如此,通过&str而不是str的代码的行为通常符合作者的期望,因为C实现对两个指针使用相同的表示形式。因此scanf可能实际上收到了使%s工作所需的指针值。 7

脚语

1 C 2018 6.2.5 20.(这意味着信息来自C标准的2018年版本,ISO / IEC 9899,信息技术-编程语言-C ,第6.2.5节,第20段)。

2 C 2018 7.1.1 1.请注意,尽管strlen函数未将终止空字符视为字符串的一部分。

3 C 2018 7.21.6.1 8。

4 从技术上讲,该参数的类型应为intprintf会将其转换为unsigned char并使用该代码打印字符。 C 2018 7.21.6.1 8。

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

6 C 2018 7.21.6.2 12。

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

答案 2 :(得分:0)

String只是zero terminated char array的一种简写。因此string与“普通”数组之间没有区别。

  

Stirng值的真实地址在哪里?

数组不是指针,它们仅衰减到指针。因此,内存中没有物理空间,用于存储数组第一个元素的地址。

  

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

这不是问题-数组是内存块。因此,该块的地址与其第一个元素的地址相同。 类型是不同的。