1

为什么当我执行此代码时:

#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 个字节,我可以存储一个大小为 6 个字节的 5 个字符的字符串?

4

4 回答 4

1

使用您的 line str = "hello",您将重新分配指针以指向内存中"hello"创建的位置。您在这里所做的是与您的 有少量内存泄漏malloc,因为您不再拥有对请求的堆空间的引用。

于 2013-07-04T19:18:54.113 回答
0

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

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

于 2013-07-04T19:18:37.797 回答
0

此行将str = "hello";指针设置为指向不同的位置。(如果你尝试这样做sizeof(str),你最终会4得到一个指针大小的值。)

strlen(str)产生没有空字符的字符串长度,这就是你有5.

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

于 2013-07-04T19:21:10.177 回答
0

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

三个输出:

  1. size_t在您的系统中是四个字节。这是原因sizeof(size)是 4,但不是因为 assignment size = 4。当然,您的 printf 大小值也是 4。
  2. 其次,strlen(str)为您提供 string 的长度"hello",即由 5 个字符组成。(字符串长度不包括\0nul 字符)。
  3. C 中的字符串是char[N](数组)类型。第 3 个 pritnfsizeof("hello")值是 6因为"hello"字符串是 6 个字符长的数组(包括字符串终止\0nul,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中,如上图所示。

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

错了,实际上您并没有将“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 链接
(旁注:您永远不应该丢失动态(显式)分配的内存地址,因为当您使用 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没有分配足够的空间来保存完整的字符串,这样做会导致缓冲区溢出问题,即运行时 C/C++ 中的未定义行为。

于 2013-07-04T19:31:18.510 回答