[英]What is memset doing to a float array?
我最近在网上找到了一段代码,看起来有点像这样:
#include <stdio.h>
#include <string.h>
int main() {
float m[10];
memset(m, 0, 20);
}
我还看到了一个片段,我认为它是正确的:
memset(m, 0, sizeof m);
尝试使用此代码段打印出第一个示例的所有值时:
for (int i = 0; i < 20; i++) {
printf("%f, \n", m[i]);
}
它产生一个 output 像这样:
0.000000,
0.000000,
0.000000,
0.000000,
0.000000,
0.000000,
0.000000,
0.000000,
0.000000,
0.000000,
-0.000000,
-4587372491414098149376.000000,
-0.000013,
0.000000,
0.000000,
0.000000,
0.000000,
0.000000,
0.000000,
0.000000
重新编译时值发生变化的地方。
现在我有几个问题:
float
-array,为什么不能使用char
-array 执行此操作?memset
的值例如1
不会更改 output?为什么 memset 可以比分配的更多写入
float
-array,为什么不能使用char
-array 执行此操作?
memset(m, 0, 20);
,正如问题最初显示的那样,写入的内容不超过分配的内容。 通常, float
在 C 实现中是四个字节,所以float m[10];
分配 40 个字节和memset(m, 0, 20);
写 20。
在新代码中, memset(m, 0, sizeof m);
向m
写入尽可能多的字节,不多也不少。
如果要求memset
写更多,您可以尝试这样做的原因是 C 实现通常不进行安全检查操作,而 C 标准不要求它们这样做。
为什么如此不一致?
没有什么不一致的。 memset
将零写入m
的前 20 个字节,这是浮点零的编码,采用float
常用的格式(IEEE-754 binary32,也称为“单精度”)。
之后的字节没有被写入,因此打印它们使用未初始化的数据。 C 标准说未初始化对象的值是不确定的。 一个常见的结果是程序已经使用了 memory 中的任何内容。 那可能是零,也可能是其他东西。
但是, for (int i = 0; i < 20; i++)
的循环,您 go 超出了m
中的 10 个元素。 那么访问m[i]
的行为不是由 C 标准定义的。 如上所述,一个常见的结果是程序访问计算的 memory 并使用发生的任何内容。 但是,其他各种行为也是可能的,包括由于尝试访问未映射的 memory 或编译器在优化期间用替代代码替换未定义代码而导致的崩溃。
为什么更改
memset
的第二个值不会更改 output?
它将取决于您将其更改为什么。 字节的某些值可能会导致float
值非常小,它们仍然打印为“0.000000”。 例如,如果将字节设置为 1,使每个float
中的 32 位0x01010101
,它们表示float
值2.36942782761723955384693006253917004604239556833255136345174597127722672385008451101850084511018181850084511018181818
如果您使用 64 作为memset
的第二个参数,则这些位将设置为0x40404040
,它对值 3.0039215087890625 进行编码,因此将打印“3.003922”。
Memset
对float
组没有任何作用。 您只有一个包含 10 个浮点数的数组,并且您使用了一个覆盖 20 个浮点数的循环,这意味着,由于 C 不检查数组边界……您已经从数组的末尾扩展了很远,并将其解释为浮点数不是。 我不会在这里重复其他答案中已经说过的内容,但是您在调整 C 对象的大小时遇到了问题。 sizeof
运算符是您的朋友。 在将 arguments 传递给memcpy
或malloc
等函数时使用它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.