为什么我在字符串缓冲区中获得不同的大小?

时间:2013-07-04 19:15:55

标签: c string malloc buffer

为什么我执行此代码时:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(){
    size_t size = 4;
    char *str = malloc(size);
    str = "hello";
    printf("malloc %s: %d\n", str, size);
    printf("strlen %s: %d\n", str, strlen(str));
    printf("sizeof %s: %d\n", str, sizeof("hello"));
    return 0;
}

我获得以下内容:

malloc hello: 4
strlen hello: 5
sizeof hello: 6

基本上,我只需要知道为什么如果我只分配4个字节,我可以存储一个字符串,其中包含5个大小为6个字节的字符?

4 个答案:

答案 0 :(得分:1)

使用您的行str = "hello",您将指针重新指定为指向内存中创建"hello"的位置。你在这里做的是你的malloc内存泄漏很小,因为你不再引用所请求的堆空间。

答案 1 :(得分:0)

str = "hello"只需重新指定指针;它不会在您刚分配的内存中存储任何内容。你刚刚创建了内存泄漏!

要复制字符串内容本身,您应该使用strncpy()

答案 2 :(得分:0)

此行str = "hello";将指针设置为指向其他位置。 (如果您尝试执行sizeof(str),最终会得到值4,这是指针的大小。)

strlen(str)生成不带空字符的字符串长度,这就是5的原因。

sizeof("hello")计算存储"hello"所需的内存,因此它也考虑了空字符,这就是输出为6的原因。所以基本上你的字符串有6个字符。

答案 3 :(得分:0)

  

Q1。 为什么我在字符串缓冲区中获得不同的大小?

三个输出:

  1. size_t是您系统中的四个字节。这就是sizeof(size)为4,但的原因,因为作业size = 4。当然,你的printf尺寸值也是4.
  2. 其次,strlen(str)为您提供字符串"hello"的长度,由5个字符组成。 (字符串长度不包括\0 nul char)。
  3. C中的字符串是char[N](数组)类型。在第3个pritnf中,sizeof("hello")的值为6,因为"hello"字符串是6个字符长数组(包括字符串终止\0 nul,hello的类型是char[6])。

    在内存"hello"中,字符串存储在图表中,如下所示:

     str          23   24   25   26   27   28
    +----+      +----+----+----+----+----+----+
    | 23 |      | h  | e  |  l | l  | o  | \0 |    
    +----+      +----+----+----+----+----+----+
    
    Address of hello string is first address = 23  
    str: is pointer, used to store address of hello string
    

    赋值str = "hello";,基本上将字符串hello的地址存储到指针变量str,如上图所示。

  4.   

    Q2。 为什么我只分配4个字节,我可以存储一个字符串,其中包含5个大小为6字节的字符

    错了,实际上你并没有将“hello”字符串复制到动态分配的空间中。最初str包含malloc()返回的地址。但是由于赋值语句str = "hello";,您在赋值语句中用常量字符串文字“hello”覆盖了已分配内存的内存地址。

    要理解这一点,您可以执行一个示例:

    #include<stdio.h>
    int main(){
     size_t size = 6;
     char *str = malloc(size);
     printf("\n malloc str: %p", str);
     str = "hello"; 
     printf("\n hello str: %p", str);
     return 1;
    }
    

    输出:

     malloc str: 0x804a078
     hello str: 0x8048609  // allocated address lost
    

    Codepade link
    (旁注:你永远不应该丢失动态(显式)分配内存的地址,因为当你使用free()显式释放它时需要它。

    如果要复制到已分配的空间,可以通过访问/索引每个内存位置来分配(1),或者(2)使用库函数strcpy()

    例如尝试:

           str[0] = 'a';
           str[1] = 'b';
           str[2] = 'c';
           str[3] = '\0';  // nul termination is important 
        or 
           strcpy(str, "abc");  // strcpy add nul itself
    

    但是你无法复制"hello"字符串,因为str没有分配足够的空间来容纳完整的字符串,这样做会导致buffer-overrun问题,即C {/ 3}} C ++在运行时。