int *ptr = malloc(sizeof(char)); *ptr = 100000; printf("%d\n", *ptr); // 100000
这不应该只为char分配足够的内存吗?那么最大的数不应该是255吗?如何打印100000?
char
100000
谢谢你的回答。如果它覆盖了下一个字节,那么C如何知道这个数字大于一个字节,而不仅仅是看第一个字节?
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)。
malloc
%d
int
char *ptr; *ptr = 100000;
at0kjp5o2#
简短回答:你通过写入不属于你的内存来调用未定义的行为,所以你永远不知道你会得到什么。它可能只是工作,它可能崩溃,或者它可能做任何数量的其他事情。在本例中,您将int放在ptr引用的位置,这将int的第一个字节写入1字节分配区域,并销毁随后三个字节中的任何内容。当使用%d说明符读回值时,printf从内存中读取sizeof(int)字节,并将其打印为int。如果你只想输出一个字节的值,你需要做如下操作:
ptr
printf
sizeof(int)
printf("%d\n", *(char*)ptr);
也就是说,告诉编译器ptr引用char,然后获取char值,该值在参数列表中被提升为int,随后由%d说明符正确输出。
dgtucam13#
这是3字节溢出。像这样从stackoverflow标志溢出,但在堆上不是堆栈。
rt4zxlrg4#
最简单的答案是:也不能保证一定有效基本上,您正在破坏指针周围的内存。
ojsjcaue5#
回答您更新的问题; C“看到”*ptr,即ptr的内容,其中ptr指向整数。所以它从这个ptr中读取一个整数。它已经忘记了你只分配了一个字符。这两个部分(分配和访问)并没有被你在代码中表达的任何东西联系起来。
7gcisfzg6#
一般来说,malloc分配内存的粒度比单个字节更大,因此您对单个字节的请求将保留一个四舍五入到最接近的8个字节的内存空间。然后你写这个空间,愉快地去过去你保留的权利。然后解引用指针,带回一个int,并将其交给printf,printf很乐意将其打印出来。正如其他人所说,依赖这种行为是一个坏主意,坏主意。分配你所需要的,不要超出你的缓冲区。
6条答案
按热度按时间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)。
at0kjp5o2#
简短回答:你通过写入不属于你的内存来调用未定义的行为,所以你永远不知道你会得到什么。它可能只是工作,它可能崩溃,或者它可能做任何数量的其他事情。在本例中,您将
int
放在ptr
引用的位置,这将int
的第一个字节写入1字节分配区域,并销毁随后三个字节中的任何内容。当使用
%d
说明符读回值时,printf
从内存中读取sizeof(int)
字节,并将其打印为int
。如果你只想输出一个字节的值,你需要做如下操作:也就是说,告诉编译器
ptr
引用char
,然后获取char
值,该值在参数列表中被提升为int
,随后由%d
说明符正确输出。dgtucam13#
这是3字节溢出。像这样从stackoverflow标志溢出,但在堆上不是堆栈。
rt4zxlrg4#
最简单的答案是:也不能保证一定有效
基本上,您正在破坏指针周围的内存。
ojsjcaue5#
回答您更新的问题; C“看到”*ptr,即ptr的内容,其中ptr指向整数。所以它从这个ptr中读取一个整数。它已经忘记了你只分配了一个字符。这两个部分(分配和访问)并没有被你在代码中表达的任何东西联系起来。
7gcisfzg6#
一般来说,
malloc
分配内存的粒度比单个字节更大,因此您对单个字节的请求将保留一个四舍五入到最接近的8个字节的内存空间。然后你写这个空间,愉快地去过去你保留的权利。然后解引用指针,带回一个int
,并将其交给printf
,printf
很乐意将其打印出来。正如其他人所说,依赖这种行为是一个坏主意,坏主意。分配你所需要的,不要超出你的缓冲区。