为什么在一个字节中分配一个大数字在C中工作?

kmynzznz  于 2023-05-16  发布在  其他
关注(0)|答案(6)|浏览(124)
int *ptr = malloc(sizeof(char));

*ptr = 100000;

printf("%d\n", *ptr); // 100000

这不应该只为char分配足够的内存吗?那么最大的数不应该是255吗?
如何打印100000

更新

谢谢你的回答。如果它覆盖了下一个字节,那么C如何知道这个数字大于一个字节,而不仅仅是看第一个字节?

ma8fv8wu

ma8fv8wu1#

因为C没有内存的范围检查。它分配一个字节,然后你通过指针的赋值覆盖它和接下来的三个字节。如果在第一个malloc之后,但在赋值之前,您分配了另一位内存,则可能会覆盖堆的一部分(取决于malloc的工作方式)。
这就是为什么指针在C中是非常危险的。
format语句中的%d(加上变量的类型)告诉编译器您正在查看int,并访问所有四个字节。
请注意,如果你真的把值赋给了一个char,例如char *ptr; *ptr = 100000;
那么在某些编译器中(假设普通的char被视为有符号的但默认的),它将输出-96,而不是255(或127)。这是因为编译器不会自动将值限制为最大值(有符号字符为127,无符号字符为255),而是溢出。大多数编译器会抱怨你试图分配一个溢出变量的常量值。
它是-96的原因是100000% 256是160,但作为有符号的char,它被输出为-(256-160)。

at0kjp5o

at0kjp5o2#

简短回答:你通过写入不属于你的内存来调用未定义的行为,所以你永远不知道你会得到什么。它可能只是工作,它可能崩溃,或者它可能做任何数量的其他事情。在本例中,您将int放在ptr引用的位置,这将int的第一个字节写入1字节分配区域,并销毁随后三个字节中的任何内容。
当使用%d说明符读回值时,printf从内存中读取sizeof(int)字节,并将其打印为int。如果你只想输出一个字节的值,你需要做如下操作:

printf("%d\n", *(char*)ptr);

也就是说,告诉编译器ptr引用char,然后获取char值,该值在参数列表中被提升为int,随后由%d说明符正确输出。

dgtucam1

dgtucam13#

这是3字节溢出。像这样从stackoverflow标志溢出,但在堆上不是堆栈。

rt4zxlrg

rt4zxlrg4#

最简单的答案是:也不能保证一定有效
基本上,您正在破坏指针周围的内存。

ojsjcaue

ojsjcaue5#

回答您更新的问题; C“看到”*ptr,即ptr的内容,其中ptr指向整数。所以它从这个ptr中读取一个整数。它已经忘记了你只分配了一个字符。这两个部分(分配和访问)并没有被你在代码中表达的任何东西联系起来。

7gcisfzg

7gcisfzg6#

一般来说,malloc分配内存的粒度比单个字节更大,因此您对单个字节的请求将保留一个四舍五入到最接近的8个字节的内存空间。然后你写这个空间,愉快地去过去你保留的权利。然后解引用指针,带回一个int,并将其交给printfprintf很乐意将其打印出来。
正如其他人所说,依赖这种行为是一个坏主意,坏主意。分配你所需要的,不要超出你的缓冲区。

相关问题