在malloc分配的内存上使用sizeof()

15

可能重复:
关于malloc和sizeof的新手问题

我正在尝试将字符串读入程序。当我注意到字符串有时会被破坏时,我尝试了以下代码:

 void *mallocated = malloc(100);
 printf("sizeof(mallocated) = %d\n", sizeof(mallocated));

根据我的程序,mallocated的大小是8,即使我为它分配了100个字节。因此,每当我尝试存储超过8个字节的字符串时,第8个字节后面的一切有时都会消失。这是为什么,如何防止它发生?

4
sizeof(mallocated)会给你void*的大小,在你的64位系统上是8个字节。你如何将一个字符串赋值给该变量,使用strcpy吗? - tur1ng
请参见:https://dev59.com/tXI_5IYBdhLWcg3wFu7L - Shog9
你的结论也是错误的,第8个“字节”(不是位)后面写的任何内容并不会随机消失。 - Blindy
5个回答

20

因为 "string" 指针的大小为 8 字节。以下是一些使用 sizeof() 的示例及其适当的 "size"。对于不习惯使用它的人来说,术语 size_of() 有时会误导。在您的情况下,指针的大小为 8 字节。下面是在典型的 32 位系统上的表示。

sizeof (char)   = 1
sizeof (double) = 8
sizeof (float)  = 4
sizeof (int)    = 4
sizeof (long)   = 4
sizeof (long long)  = 8
sizeof (short)  = 2
sizeof (void *) = 4

sizeof (clock_t)    = 4
sizeof (pid_t)  = 4
sizeof (size_t) = 4
sizeof (ssize_t)    = 4
sizeof (time_t) = 4

来源

你遗漏了如何确定你的字符串被删除(字符数组)。它可能被传递给一个函数,你需要将明确的长度作为变量传递或在某个地方跟踪它。使用sizeof()不能告诉你这一点。

请参考我的之前的问题,你会看到我最初的理解也很有限。


1
感谢您的帮助。程序的问题并不完全是我想象中的那样(它有时候会这样吧?),但是您的建议非常有用。 - Michael Dickens

15

在C89中,sizeof运算符仅在编译时以字节为单位查找变量的大小(在本例中为8字节的void指针)。 它对于普通数组的工作方式与您预期的相同,因为它们的大小在编译时已知。

char arr[100]; // sizeof arr == 100
char *p = arr; // sizeof p == 4 (or 8 on 64-bit architectures)
char *p = malloc(100); // sizeof p == 4 (or 8). Still!

要知道堆分配内存的大小,你需要手动跟踪它,sizeof 不能帮助你。


4
不是这样的。在C99中,sizeof返回变长数组的大小,而变长数组的大小在许多情况下只能在运行时确定。 - dreamlax
2
谢谢,我在答案中排除了C99的情况,以保持简单。 - Alex B

9

sizeof 函数返回您提供的指针(void *)的大小,而不是您分配的内存大小。如果您想后续使用已分配内存的大小,则需要将其存储在一个单独的变量中。


5

您无法获取malloc分配的void *大小,但这并不能告诉您太多信息。

无法获取分配的*mallocated的大小。也就是说,除非编写自己的内存管理例程,否则没有函数调用可以返回100(在您的示例中)。

最简单的方法只是在某个地方记住它...也许....

stuct {
  void *data;
  unsigned int size
 } myStructureWhichRemebersItsSize;

myStructureWhichRemebersItsSize *someData;
someData.data = malloc(100);  // and check for NULL
someData.size = 100;

1
你不能获取已分配内存的大小...这并不是绝对的,它取决于你的C库。在微软的CRT STDLIB下,你可以简单地调用_msize(*mallocated)来获取OP所需的“100”。 - Clinton Pierce
+1 谢谢提供信息。我不使用微软,所以不知道这个。这是一个有用的功能,在更多地方看到会很不错。当然,在幕后,编译器可能正在生成我所描述的结构。 - Mawg says reinstate Monica
1
如果 someData 被声明为指针,你必须使用 '->' 运算符来访问它的字段。 - PintoDoido

-1

void* 是内存中的一个位置类型,如果你不知道它包含什么内容,应该避免使用。

char* 是指向内存中某个包含 char 的位置的值的类型。识别内存中的位置需要8个字节。

sizeof 告诉你一个特定类型占用多少字节。它不告诉你使用 malloc 分配了多少内存,而是编译器知道该类型应该占用多少内存。对值应用 sizeof 通常被认为是不好的风格,正如其他人在这里提到的,有时会在 C99 中调用智能行为。

char[100] 是一个包含100个字符的值的类型。 char[100] a; 是栈上的100个 char 字符串。

char(*)[100] 是指向包含100个字符的值的指针类型。 char(*b)[100]; 使 b 指向100个字符,可能在堆上。你可能想要的是

char (*s)[100] = malloc( sizeof( char[100] ) );
printf( "%u byte pointer to %u bytes of size %u elements\n",
  sizeof s, sizeof *s, sizeof **s );

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接