memset操作float数组的行为表现及相关技术问题咨询
前置说明
主流编译环境下float类型占4字节,你定义的float m[10]总分配大小为40字节。你第一版代码里memset(m, 0, 20)仅初始化了前20字节(对应前5个float元素),剩余的数组空间未做初始化;且你打印时循环条件写的是i < 20,访问范围远远超出了数组仅有的10个元素的边界,属于典型的未定义行为。
问题解答
- 关于越界写入的疑问:
你对memset的能力认知存在错误,memset本身是底层内存操作函数,不会对任何类型的数组做边界检查,不管是float数组还是char数组,只要你传入的长度参数超过了数组实际分配的大小,都属于越界写入的未定义行为。不是char数组不能越界,只是你之前测试char数组时刚好触发了崩溃、脏数据等明显异常,才产生了不能越界的错觉,本质上两种数组的越界操作都是C语言严格禁止的。 - 关于输出不稳定的疑问:
未初始化的栈内存和越界访问的内存区域,存储的都是程序运行过程中残留的随机垃圾值,不同编译选项、不同运行时刻栈的布局和残留值都会发生变化,打印出来的结果自然每次都不一样,这是未定义行为的典型表现。 - 关于修改memset第二个参数无变化的疑问:
不是没有变化,是你的打印方式不足以识别出差异。memset是逐字节填充内存,第二个参数会被转为unsigned char类型赋值给每个字节,当你传1时,前5个float对应的内存就是0x01010101,对应的单精度浮点数值约为2.3694e-38,是个极小的正数,用默认保留6位小数的%f格式打印时会直接显示为0.000000,和全0的打印结果看起来一致。你换成%g或者保留更多小数位的格式(比如%.15f)打印,就能看到明显的数值差异。
内容的提问来源于stack exchange,提问作者gurkensaas
相关产品推荐
相关产品推荐

