简体   繁体   English

memset 对浮点数组做了什么?

[英]What is memset doing to a float array?

I recently found a piece of code online which looked a little like this:我最近在网上找到了一段代码,看起来有点像这样:

#include <stdio.h>
#include <string.h>

int main() {
    float m[10];
    memset(m, 0, 20); 
}

I also saw a snippet where it was like this which I believe to be correct:我还看到了一个片段,我认为它是正确的:

memset(m, 0, sizeof m); 

When trying to print out all the values of the first example using this snippet:尝试使用此代码段打印出第一个示例的所有值时:

for (int i = 0; i < 20; i++) {
    printf("%f, \n", m[i]);
}

It produces an output like this:它产生一个 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

Where the values change on recompilation.重新编译时值发生变化的地方。

Now I have a few questions:现在我有几个问题:

  • Why can memset write to a float -array more than what was allocated and why can't you do that with a char -array?为什么 memset 可以比分配的更多写入float -array,为什么不能使用char -array 执行此操作?
  • Why is it so inconsistent?为什么如此不一致?
  • Why does changing the second value to value of memset to 1 for example not change the output?为什么将第二个值更改为memset的值例如1不会更改 output?

Why can memset write to a float -array more than what was allocated and why can't you do that with a char -array?为什么 memset 可以比分配的更多写入float -array,为什么不能使用char -array 执行此操作?

memset(m, 0, 20); , as the question originally showed, does not write more than was allocated. ,正如问题最初显示的那样,写入的内容不超过分配的内容。 Commonly, float is four bytes in C implementations, so float m[10];通常, float在 C 实现中是四个字节,所以float m[10]; allocates 40 bytes, and memset(m, 0, 20);分配 40 个字节和memset(m, 0, 20); writes 20.写 20。

In the new code, memset(m, 0, sizeof m);在新代码中, memset(m, 0, sizeof m); writes just as many bytes to m as it has, no fewer and no more.m写入尽可能多的字节,不多也不少。

If memset were asked to write more, the reason you can try to do that is C implementations generally do not safety check operations, and the C standard does not require them to.如果要求memset写更多,您可以尝试这样做的原因是 C 实现通常不进行安全检查操作,而 C 标准不要求它们这样做。

Why is it so inconsistent?为什么如此不一致?

There is nothing inconsistent.没有什么不一致的。 memset wrote zeros to the first 20 bytes of m , and that is the encoding for floating-point zero, in the format commonly used for float (IEEE-754 binary32, also called “single precision”). memset将零写入m的前 20 个字节,这是浮点零的编码,采用float常用的格式(IEEE-754 binary32,也称为“单精度”)。

The bytes after that were not written, so printing them uses uninitialized data.之后的字节没有被写入,因此打印它们使用未初始化的数据。 The C standard says the values of uninitialized objects are not determined. C 标准说未初始化对象的值是不确定的。 A common result is the program uses whatever happened to be in the memory already.一个常见的结果是程序已经使用了 memory 中的任何内容。 That may be zeros, or it may be something else.那可能是零,也可能是其他东西。

However, with the loop for (int i = 0; i < 20; i++) , you go beyond the 10 elements that are in m .但是, for (int i = 0; i < 20; i++)的循环,您 go 超出了m中的 10 个元素。 Then the behavior of accessing m[i] is not defined by the C standard.那么访问m[i]的行为不是由 C 标准定义的。 As above, a common result is the program accesses the calculated memory and uses whatever happens to be there.如上所述,一个常见的结果是程序访问计算的 memory 并使用发生的任何内容。 However, a variety of other behaviors are also possible, including crashing due to an attempt to access unmapped memory or the compiler replacing the undefined code with alternate code during optimization.但是,其他各种行为也是可能的,包括由于尝试访问未映射的 memory 或编译器在优化期间用替代代码替换未定义代码而导致的崩溃。

Why does changing the second value of memset not change the output?为什么更改memset的第二个值不会更改 output?

It will, depending on what you change it to.它将取决于您将其更改为什么。 Some values for the byte may result in float values that are so small they are still printed as “0.000000”.字节的某些值可能会导致float值非常小,它们仍然打印为“0.000000”。 For example, if bytes are set to 1, making the 32 bits 0x01010101 in each float , they represent a float value of 2.36942782761723955384693006253917004604239556833255136345174597127722672385008451101384707726538181•10 −38 .例如,如果将字节设置为 1,使每个float中的 32 位0x01010101 ,它们表示float2.36942782761723955384693006253917004604239556833255136345174597127722672385008451101850084511018181850084511018181818

If you use 64 for the second argument to memset , the bits will be set to 0x40404040 , which encodes the value 3.0039215087890625, so “3.003922” will be printed.如果您使用 64 作为memset的第二个参数,则这些位将设置为0x40404040 ,它对值 3.0039215087890625 进行编码,因此将打印“3.003922”。

Memset is doing nothing to a float array. Memsetfloat组没有任何作用。 You just had an array of 10 floats and you use a loop that is covering 20, this means that, as C doesn't check for array bounds... you have extended far from the end of the array and interpreting as float things that are not.您只有一个包含 10 个浮点数的数组,并且您使用了一个覆盖 20 个浮点数的循环,这意味着,由于 C 不检查数组边界……您已经从数组的末尾扩展了很远,并将其解释为浮点数不是。 I will not repeat here what has already been said in other answers, but you have a problem on sizing C objects.我不会在这里重复其他答案中已经说过的内容,但是您在调整 C 对象的大小时遇到了问题。 The sizeof operator is your friend here. sizeof运算符是您的朋友。 Use it when passing arguments to functions like memcpy or malloc .在将 arguments 传递给memcpymalloc等函数时使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM