c语言memset函数,深入学习C语言中memset()函数的用法

memset()函数用于将内存区域填充特定值,常用于初始化字符数组。但在C++中,对于包含虚函数的类,使用memset可能导致虚表破坏,造成运行时错误。栈上创建的带虚类对象可能不会立即出现问题,而堆上创建的则会。慎用memset对带虚类对象进行清零操作,应使用构造函数或成员wise拷贝确保正确初始化。
摘要由CSDN通过智能技术生成

2015

头文件:

1#include

memset() 函数用来将指定内存的前n个字节设置为特定的值,其原型为:

1void *memset(void * ptr,int value,size_t num );

参数说明:

ptr 为要操作的内存的指针。

value 为要设置的值。你既可以向 value 传递 int 类型的值,也可以传递 char 类型的值,int 和 char 可以根据 ASCII 码相互转换。

num 为 ptr 的前 num 个字节,size_t 就是unsigned int。

【函数说明】memset() 会将 ptr 所指的内存区域的前 num 个字节的值都设置为 value,然后返回指向 ptr 的指针。

memset() 可以将一段内存空间全部设置为特定的值,所以经常用来初始化字符数组。例如:

1

2char str[20];

memset(str,'\0',sizeof(str)-1);

【返回值】返回指向 ptr 的指针。

注意:参数 value 虽声明为 int,但必须是 unsigned char,所以范围在0 到255 之间。

范例:

1

2

3

4

5

6

7

8

9

10

11

12#include

#include

#include

int main()

{

// 不可以声明为 char *str = "http://c.biancheng.net";

memset(str,'-', 7);

puts(str);

system("pause");

return EXIT_SUCCESS;

}

执行结果:

1-------c.biancheng.net

优化:尽量用memset将一个数组设置清零(带虚类除外),而不是通过for循环逐个置0

下面这个例子,大家可以参考:3D游戏编程大师技巧。本文其实重点是memset,原因是在工作中,用的比较多。

例如:要清空一个float f[10000],应该用memset(f,0,sizeof(float) * 10000);

而不是: for(int i=0; i<10000; ++i) f[i] = 0;

当然,还可以用内嵌汇编的形式:

1

2

3

4

5

6

7_asm

{

mov edi, f;// edi指向数组地的目标内存的起始处

mov ecx, 1000/4;// 循环次数或移动次数

mov eax, 0;// 每一次移动32位数,都置0

rep stosd;// 移动数据

}

哈,这个准则有个前提,那就是带虚的类除外,原因是,memset将类清空,有可能将虚表也给置0了。

有可能是因为:类的创建分:栈上和堆上。

如果在栈上,那么栈对象的虚函数调用可能会在静态时确定,从而绕过虚表。所以不会出错。

但堆上就一定会出错,下面给出测试代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38class CMemsetVirtualTest// 测试 带虚类,被memset为0后,虚表是否失效

{

public:

CMemsetVirtualTest()

{

memset(this,0,sizeof(CMemsetVirtualTest));

}

virtual void NormalFun()

{

cout<

}

virtual ~CMemsetVirtualTest()

{

cout<

}

};

void testFun1()// 测试:栈上建立的对象

{

CMemsetVirtualTest Ctest;

Ctest.NormalFun();

}

void testFun2()// 测试:堆上建立的对象

{

CMemsetVirtualTest* Ptest =new CMemsetVirtualTest();

Ptest->NormalFun();// 到这里一定会暴掉

delete Ptest;// 如果屏蔽上句,到这里也一定会暴掉

}

int main()

{

CMemsetVirtualTest Ctest;// 测试:栈上建立的对象

Ctest.NormalFun();// 测试正常:

CMemsetVirtualTest* Ptest =new CMemsetVirtualTest();// 测试:堆上建立的对象

Ptest->NormalFun();// 到这里一定会暴掉

delete Ptest;// 如果屏蔽上句,到这里也一定会暴掉

}

即:

在C++中,涉及虚技术的类,他的对象内存区块中就不单纯是用户定义这个类时看上去的那些数据结构,编译器会在当中安插一些数据或代码,用来实现响应的虚技术.于是当你用memset函数时会把这些编译器安插的东西冲掉, 程序执行结果变得未知. 这时候如果拷贝对象C++会使用memberwise拷贝, 此时编译器既拷贝用户定义的数据结构,还会对支持虚技术的相关设施进行适当的修改.

如果对象没有用到虚技术, 那么就可以使用memset,就跟正常情况一样,可以逐位拷贝.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值