memset()函数中的坑

一 写在开头
1.1 本节内容
内存填充函数memset()中的坑。

二 函数原型

1 /* 来自man memset */
2 #include <string.h>
3 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()正确的应用场景。下面的代码能够很好地运行,完全能够达到目的。

 1 #include <stdio.h>
 2 #include <string.h>
 3
 4 int main(int argc, char *argv[])
 5 {
 6     char Queen[10];
 7
 8     memset(Queen, ‘G‘, sizeof(Queen));
 9
10     return 0;
11 }

调用memset()函数之前:
(gdb) p Queen
$1 = "\360\[email protected]\000\000\000\000\000\240\004"
调用memset()函数之后:
(gdb) p Queen
$2 = "GGGGGGGGGG"

如果Queen数组类型不是char而是int,结果会怎样?

 1 #include <stdio.h>
 2 #include <string.h>
 3
 4 int main(int argc, char *argv[])
 5 {
 6     int Queen[10];
 7
 8     memset(Queen, ‘G‘, sizeof(Queen));
 9
10     return 0;
11 }

调用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 第二个坑
在成功避开第一个坑之后,你可能还会遇到第二个坑。比如说,你把上述的代码写成了下面的这个样子。

 1 #include <stdio.h>
 2 #include <string.h>
 3
 4 int main(int argc, char *argv[])
 5 {
 6     int Queen[10];
 7
 8     memset(Queen, -1, 10);
 9
10     return 0;
11 }

调用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

时间: 2024-10-09 03:22:15

memset()函数中的坑的相关文章

透彻分析C/C++中memset函数

原文:http://blog.csdn.net/dan15188387481/article/details/49621447 在C语言中,经常需要对内存进行操作,里面涉及很多函数,但是memset函数的使用有一点需要大家格外注意,这也是我在做项目时遇到过的一个问题,调试了很久才找出来错误. 函数原型是:void *memset(void *s, int ch, size_t n); 函数功能是:将s所指向的某一块内存中的前n个字节的内容全部设置为ch指定的ASCII值, 第一个值为指定的内存地

Torch-RNN运行过程中的坑 [2](Lua的string sub函数,读取中文失败,乱码?)

0.踩坑背景 仍然是torch-rnn/LanguageModel.lua文件中的一些问题,仍然是这个狗血的LM:encode_string函数: function LM:encode_string(s) local encoded = torch.LongTensor(#s) for i = 1, #s do local token = s:sub(i, i) local idx = self.token_to_idx[token] assert(idx ~= nil, 'Got invali

C/C++中memset函数

本文学习参考http://baike.baidu.com/link?url=ZmSyY8ciB_nJt9KM-W2fiEFJrC2mugFsLqRdY2b4pLe8rD_jRXyN7_pj0GBBD2bKyt6Xm-lpUlAO97H94dUYXa 1.memset函数的声明和含义如下: 函数解释:将s所指向的某一块内存中的前n个字节的内容全部设置为 ch 指定的 ASCII值, 第一个值为指定的内存地址,块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作, 其返回值为指向s的指针

C++中的memset()函数 ------------转自:http://www.360doc.com/content/10/1006/18/1704901_58866679.shtml

memset()函数可以对大内存的分配进行很方便的操作(初始化),所谓"初始化",当然是指将你定义的变量或申请的空间赋予你所期望的值,例如语句int i=0;就表明定义了一个变量i,并初始化为0:如果int j=5;就表明定义了一个变量j,并初始化为5. 但是对于大块儿内存的分配,这种方法当然不行,例如int arr[100];定义了数组arr,包含100个元素,如果你写成int arr[100]=0;想将数组全部内容初始化为0,是不行的,连编译都不能通过.这种情况的初始化,有两种方法

在python函数中默认参数的一些坑

一.默认参数 python为了简化函数的调用,提供了默认参数机制: 这样在调用pow函数时,就可以省略最后一个参数不写: 在定义有默认参数的函数时,需要注意以下: 必选参数必须在前面,默认参数在后: 设置何种参数为默认参数?一般来说,将参数值变化小的设置为默认参数. python标准库实践 python内建函数: 函数签名可以看出,使用print('hello python')这样的简单调用的打印语句,实际上传入了许多默认值,默认参数使得函数的调用变得非常简单. 二.出错了的默认参数 引用一个官

memset初始化数组的坑

memset函数常被我们用来初始化数组,然而有个坑可能会被我们踩到. 静态数组初始化 一般情形是这样的: #include <cstring> int main() { // 静态数组arr int arr[10]; // 将数组所有元素初始化为0 memset(arr,0,sizeof(arr)); // 遍历输出数组元素 for(int i=0;i<10;++i){ cout << arr[i] << endl; } return 0; } 这样做是正确的,通

memset()函数

1. memset()函数原型是extern void *memset(void *buffer, int c, int count)        buffer:为指针或是数组, c:是赋给buffer的值, count:是buffer的长度. 这个函数在socket中多用于清空数组.如:原型是memset(buffer, 0, sizeof(buffer)) Memset 用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为' '或'/0': 例:char a[100];

strcpy, memcpy, memset函数

一. strcpy函数 原型声明:char *strcpy(char* dest, const char *src); 头文件:#include <string.h> 和 #include <stdio.h> 功能:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间 说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串. 返回指向dest的指针. 实现代码: char * strcpy(char * strDest,c

Linux编程中的坑——C++中exit和return的区别

今天遇到一个坑,折腾了一天才把这个坑填上,情况是这样的: 写了段代码,在main()函数中创建一个分离线程,结果这个线程什么都没干就直接挂掉了,代码长这样: [cpp] view plain copy int main() { 创建一个分离线程(): return 0: } 后来百度)了一下,原来在main()函数中写return,会被编译器优化成,也会像exit一样直接杀死所有进程,所以分离出来的线程什么都没干,就随着进程一起挂掉了. 所以多线程编程中,main()函数想退出线程应当使用 [c