为什么在一个字节中分配一个大数字在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
,然后快乐地将它打印出来。
正如其他人所说,取决于这种行为是一个坏主意。 准确分配您需要的内容,不要超出缓冲区。