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

int *ptr = malloc(sizeof(char)); *ptr = 100000; printf("%d\n", *ptr); // 100000 

不应该只为char分配足够的内存,即1个字节? 因此最大数量不应该是255?

它如何打印100000

更新

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

因为C没有内存范围检查。 它分配一个字节,然后通过指针的赋值覆盖它和接下来的三个字节。 如果你在第一个malloc之后立即分配了另一部分内存,但是在赋值之前,你可能已经覆盖了部分堆(取决于你的malloc如何工作)。

这就是为什么指针在C中可能非常危险的原因。

格式语句中的%d(加上变量的类型)告诉编译器您正在查看int,并访问所有四个字节。

请注意,如果您确实已将值分配给char,例如char * ptr; * ptr = 100000;

然后使用一些编译器(假设普通字符被视为已签名但默认值)它将打印出-96而不是255(或127)。 这是因为编译器不会自动将值限制为可以适合的最高值(在有符号字符中为127,在无符号字符中为255),而是仅溢出。 大多数编译器会抱怨您正在尝试分配溢出变量的常量值。

它是-96的原因是100000%256是160,但作为有符号的char,它输出为 – (256-160)。

简短的回答:你通过写入不属于你的内存来调用未定义的行为,所以你永远不知道你会得到什么。 它可能只是工作,它可能会崩溃,或者它可能会做许多其他事情。 在这种情况下,你将int放在ptr引用的位置,它将int的第一个字节写入1字节的分配区域,并粉碎后面三个字节中的任何内容。

当您使用%d格式说明符读取值时, printf从内存中读取sizeof(int)字节以将它们作为int打印。 如果只想输出一个字节的值,则需要执行以下操作:

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

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

这是3字节溢出。 像stackoverflow徽标一样溢出,但堆栈上没有堆栈。

最简单的答案是:它不能保证工作。

基本上,你正在腐蚀指针周围的内存。

回答你的最新问题; C“看到”* ptr即ptr的内容,其中ptr指向整数。 所以它从那个ptr读取一个整数。 它已经忘记你只分配了一个字符。 这两部分(分配然后访问)不会被您在代码中表达的任何内容链接。

通常, malloc将以比单个字节更大的粒度分配内存,因此您对单个字节的请求将保留一个四舍五入到最接近的8个字节的内存空间。 然后你写信给这个空间,轻快地走过你保留的东西。 然后你取消引用指针,带回一个int ,然后把它交给printf ,然后快乐地将它打印出来。

正如其他人所说,取决于这种行为是一个坏主意。 准确分配您需要的内容,不要超出缓冲区。