一 写在开头
1.1 本节内容
内存填充函数 memset() 中的坑.
二 函数原型
- /* 来自 man memset */
- #include <string.h>
- void * memset(void * s, int c, size_t n);
功能描述: memset() 函数用常量 c 的值填充由指针 s 所指向的内存地址空间的前 n 个字节的内存空间.
DESCRIPTION : The memset() function fills the first n bytes of the memory area pointed to by s with the constant byte c.
参数:
void * s - 指向要被填充的内存空间的首地址
int c - 一个常量
size_t n - 要被填充的字节数
返回值:
memset() 函数是有返回值的, 从函数原型也可以看出来. memset() 函数返回一个指向内存空间 s 的指针.
RETURN VALUE : The memset() function returns a pointer to the memory area s.
三 填坑运动
3.1 第一个坑
先举一个 memset() 正确的应用场景. 下面的代码能够很好地运行, 完全能够达到目的.
- #include <stdio.h>
- #include <string.h>
- int main(int argc, char *argv[])
- {
- char Queen[10];
- memset(Queen, 'G', sizeof(Queen));
- return 0;
- }
调用 memset() 函数之前:
- (gdb) p Queen
- $1 = "\360\005@\000\000\000\000\000\240\004"
调用 memset() 函数之后:
- (gdb) p Queen
- $2 = "GGGGGGGGGG"
如果 Queen 数组类型不是 char 而是 int, 结果会怎样?
- #include <stdio.h>
- #include <string.h>
- int main(int argc, char *argv[])
- {
- int Queen[10];
- memset(Queen, 'G', sizeof(Queen));
- return 0;
- }
调用 memset() 函数之前:
- (gdb) p Queen
- $1 = {0, 0, 0, 0, 4195824, 0, 4195488, 0, -8352, 32767}
调用 memset() 函数之后:
- (gdb) p Queen
- $2 = {1195853639, 1195853639, 1195853639, 1195853639, 1195853639, 1195853639,
- 1195853639, 1195853639, 1195853639, 1195853639}
看到了吧! Queen 数组全部被填充了一个相同的数字, 但该数字却不是我们想要的'G'. 为什么会这样? 道理很简单, memset() 函数是一个字节一个字节地填充数字的, 你一个 int 类型变量在内存中占了 4 个字节 (不同机器, int 所占字节数不一样), 不出错才怪! 上一个例子之所以能够正确运行, 是因为在我的机器上, 一个 char 类型变量刚好占了一个字节.
怎么避免这个问题? 下次记得在使用 memset() 函数对 int 型数组进行填充时, 所能够使用的常量 c 的取值只能是 0 和 - 1. 想想 0 和 - 1 这两个数的二进制表示是怎样的, 你就明白了为什么只能使用这两个数字了.
3.2 第二个坑
在成功避开第一个坑之后, 你可能还会遇到第二个坑. 比如说, 你把上述的代码写成了下面的这个样子.
- #include <stdio.h>
- #include <string.h>
- int main(int argc, char *argv[])
- {
- int Queen[10];
- memset(Queen, -1, 10);
- return 0;
- }
调用 memset() 函数之前:
- (gdb) p Queen
- $1 = {0, 0, 0, 0, 4195824, 0, 4195488, 0, -8352, 32767}
调用 memset() 函数之后:
- (gdb) p Queen
- $2 = {-1, -1, 65535, 0, 4195824, 0, 4195488, 0, -8352, 32767}
怎么回事, 为什么没有把 Queen 数组全部初始化为 - 1? 因为 memset() 函数是一个字节一个字节地填充数的! 第三个参数 10 表示的是数组 Queen 中有 10 个 int 型数据, 它并不表示 Queent 数组在内存中所占的字节数! 明白了吧!
怎么避免这个问题, 很简单, 将上述 memset() 调用改成如下的样子就好了
1 memset(Queen, -1, sizeof(Queen));
四 参考资料
1. man memset
来源: https://www.cnblogs.com/laizhenghong2012/p/9298334.html