字符串和位如何在C中起作用?

时间:2016-11-20 12:54:29

标签: c arrays string sizeof bits

我有两个问题:

  1. 了解sizeof
  2. 的输出
  3. 了解字符串如何存储在变量中(例如位和内存)
  4. 问题1

    我正在尝试理解以下C代码的输出。

    printf("a: %ld\n", sizeof("a")); // 2
    printf("abc: %ld\n", sizeof("abc")); // 4
    

    它似乎总是大于指定的实际字符数。

    文档建议返回的值表示对象的大小(在本例中为字符串),以字节为单位。因此,如果a的大小为我们提供了2个字节,那么我很好奇a如何代表16位信息。

    如果我查看ASCII字符a的二进制表示,我可以看到它是01100001。但是这只显示了1个字节中的3个比特。

    问题2

    另外,大字符串如何存储到C中的变量中?我是否正确地认为它们必须存储在数组中,如下所示:

    char my_string[5] = "hello";
    

    有趣的是,当我有一些代码时:

    char my_string = "hello";
    printf("my_string: %s\n", my_string);
    

    我遇到两个编译器错误:

    - incompatible pointer to integer conversion initializing 'char' with an expression of type 'char [6]'
    - format specifies type 'char *' but the argument has type 'char'
    

    ......我不明白。首先,它声明当只有5个字符时,类型被假定为[6]的大小。其次,这里提到一个指针对我来说似乎很奇怪?为什么printf期望一个指针,为什么不在指向整数错误的指针中指定变量/数组的长度?

    顺便说一下,我似乎可以将变量/数组的长度设置为5而不是6,它将按照我预期的char my_string[5] = "hello";工作。

    我可能只是遗漏了一些关于比特和字符串如何在C中工作的基本/基本的东西。

    理解这一点的任何帮助都将受到赞赏。

2 个答案:

答案 0 :(得分:1)

问题的第一部分是由于字符串存储在C中的方式.C中的字符串只不过是一系列字符(char),最后添加了\0,这就是你在做sizeof时看到+1的原因。请注意,如果您要说char my_string[4] = "hello";,您还会收到编译错误,说明此字符串的大小不够。这也与此有关。

现在进入第二部分,字符串本身就是一系列字符。但是,您不能将每个字符自己存储在变量中。您可以使用指针来访问这些系列字符,以便从内存的某些部分访问它们。有关C中指针和字符串的更多信息,请访问:Pointer to a String in C

答案 1 :(得分:1)

在C中,字符串是一系列字符值,后跟零值终结符。例如,字符串"hello"是字符值{'h', 'e', 'l', 'l', 'o', 0 } 1 的序列。字符串(包括字符串文字)存储char(或wchar_t的数组,用于宽字符字符串)。要考虑终结符,数组的大小必须始终大于字符串中的字符数:

char greeting[6] = "hello";

greeting的存储空间如下所示

          +---+
greeting: |'h'| greeting[0]
          +---+
          |'e'| greeting[1]
          +---+
          |'l'| greeting[2]
          +---+
          |'l'| greeting[3]
          +---+
          |'o'| greeting[4]
          +---+
          | 0 | greeting[5]
          +---+

字符串文字的存储大致相同 2

          +---+
 "hello": |'h'| "hello"[0]
          +---+
          |'e'| "hello"[1]
          +---+
          |'l'| "hello"[2]
          +---+
          |'l'| "hello"[3]
          +---+
          |'o'| "hello"[4]
          +---+
          | 0 | "hello"[5]
          +---+

是的,您可以将下标运算符[]应用于字符串文字,就像任何其他数组表达式一样。

除非它是sizeof或一元&运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,表达式为类型“N - T的元素”将被转换(“衰减”)为“指向T的指针”类型的表达式,表达式的值将是数组的第一个元素。因此,字符串文字"hello"是“char的6元素数组”类型的表达式。如果我将该文字作为参数传递给像

这样的函数
printf( "%s\n", "hello" );

然后两个字符串文字表达式 "%s""hello"都从“{4}元素char 3 和“char的6元素数组”指向“char”的指针,因此printf接收的是指针值,而不是数组值。

您已经看到转换规则有两个例外。当您使用sizeof运算符并且得到的值比您预期的多一个时,您在代码中看到了它。 sizeof计算存储操作数所需的字节数。由于零终结符,它需要N + 1个字节来存储一个N字符串。

第二个例外是上面greeting数组的声明;因为我使用字符串文字来初始化数组,所以文字不会首先转换为指针值。请注意,您可以将该声明写为

char greeting[] = "hello"; 

在这种情况下,数组的大小取自初始化程序的大小。

当数组表达式是一元&运算符的操作数时,会发生第三个异常。表达式char不是评估指向char **&greeting)的指针,而是求值为“指向 6元素数组的指针 {{ 1}}“,或char

字符串的长度是零终止符之前的字符数。处理字符串的所有标准库函数都希望看到终结符。存储该字符串的数组的 size 必须至少大于您要存储的字符串的最大长度。

<小时/>

  1. 有时您会看到人们写char (*)[6]而不是裸'\0'来表示字符串终止符;他们的意思是一样的。
  2. 字符串文字的存储在程序启动时分配,并保持到程序终止。字符串文字可以存储在只读存储器段中;尝试修改字符串文字的内容会导致未定义的行为。
  3. 0算作单个字符。