一个buff是不是用memset比较安全

hanyj_3000 2011-10-17 05:02:25
char retbuff[100] = {0};
我一般是像上面那样去定义一个buff来用,也就是定义后紧接着 = {0}去清空,紧着着我就可以用这个buff了。我以前的同事也时经常这样用的。

但是最近我一个同事说,这样用不太安全。他说最好是char retbuff[100];然后memset(retbuff,0,100);再用它就比较安全了。我不知道他说的有没有道理,因为我觉得两者没啥区别啊,怎么会不安全呢,当然,如果我其他地方再用这个buff时,我知道是该用memset的。

我的同事说的有无道理,特地向大家请教下。
...全文
306 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
yujie_v 2011-10-18
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 rendao0563 的回复:]
{0} 高效 memset 低效.
[/Quote]
这个说法也对的。
一个是编译器是确定的,一个是运行时赋值。
不过看具体情况。目前还没有遇到有什么特殊的问题的,两种情况几乎等价。
如果C/C++标准突然改变,兴许会有不同的。
rendao0563 2011-10-18
  • 打赏
  • 举报
回复
{0} 高效 memset 低效.
hanyj_3000 2011-10-18
  • 打赏
  • 举报
回复

方式1:
char buff[100] = {0};//定义并初始化清零
//紧接着使用buff。(指初次使用这个buff)

方式2:
char buff[100];
memset(buff,0,sizeof(buff[0])*100));
//再使用buff


我现在用的是VC,就上面2种方式来说,我觉得效果是一样的,不存在方式2比方式1更安全的说法,方式1同样能把100个元素全部初始化为0。如果哪位兄台认为方式1不妥,清举个例子,并说明在什么编译器下。
飞天御剑流 2011-10-17
  • 打赏
  • 举报
回复
关于char retbuff[100] = {0};不安全的是讹传。我举个在网上搜到的例子:

问:

...
wchar_t wname[128]=...{0};
char cname[256]=...{0};
...
我感兴趣的是:
1.这种赋值的结果.
2.这种形式是否符合标准编码规则?

答:

/*
初始化值的个数可少于数组元素个数.当初始化值的个数少于数组元素个数时,前面的按序初始化相应值, 后面的初始化为0(全局或静态数组)或为不确定值(局部数组).
*/
我相信上面的资料是C和C++语言的标准规范,但实际编译器处理时,可能会和规范有所不同.因为编译器原则上要遵从语言规范,但对于局部数组的不确定值到底是多少,怎么处理,编译器就可以灵活处理.我测试了三种编译器,其实编译器赋予的值是固定的,都是0.

在这篇blog中 http://hi.baidu.com/widebright/blog/item/a024bc09631402256b60fbd0.html 谈论了相同的话题



但是,回答者显然没有看过或者没有看懂C/C++标准,C90是这样说的:

6.57 Initialization
...
If there are fewer initializers in a brace-enclosed list than there are members of an aggregate, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

那么objects that have static storage duration是如何进行初始化呢,有明确规定:

If an object that has static storage duration is not initialized explicitly. it is
initialized implicitly as if every member that has arithmetic type were assigned 0 and every member that has pointer type were assigned a null pointer constant.

对于数值类型就用0初始化,对于指针用空指针常量。而C99也有类似的内容:

6.7.8 Initialization
......
If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.
.....
If an object that has static storage duration is not initialized explicitly,
then:
— if it has pointer type, it is initialized to a null pointer;
— if it has arithmetic type, it is initialized to (positive or unsigned) zero;
— if it is an aggregate, every member is initialized (recursively) according to these rules;
— if it is a union, the first named member is initialized (recursively) according to these rules.

C++则是这样规定的:

8.5 Initializers

8.5.1 Aggregates


If there are fewer initializers in the list than there are members in the aggregate, then each member not explicitly initialized shall be value-initialized (8.5). [Example:
struct S { int a; char* b; int c; };
S ss = { 1, "asdf" };
initializes ss.a with 1, ss.b with "asdf", and ss.c with the value of an expression of the form int(), that is, 0. ]



那个回答之所以是错的,是以为它遵循If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.这条规定,实则不是,对于初始化器不足聚集元素数量的初始化是另有规定的。
BT六眼飞鱼 2011-10-17
  • 打赏
  • 举报
回复
char p[100] = {0};
我上次看到书上说char类型的才可以用{0}清零
zhujian888 2011-10-17
  • 打赏
  • 举报
回复
是的,这是个好习惯。
恨天低 2011-10-17
  • 打赏
  • 举报
回复
bzero
Enter空格 2011-10-17
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 supermegaboy 的回复:]
对第一种初始化方式的担忧来源于某些编译器可能不会将后部的元素进行char()初始化,但我认为这种担忧是多余的,因为无论c还是c++,值初始化都是受标准支持的,都是标准明文规定的条款,对于内置类型,值初始化就是数值0,对于类,就是默认构造函数。

后部元素不进行值初始化就属于非标准行为了,不应该将非标准行为归咎于初始化方式,因为,如果将非标准行为归咎为原因的话,memset同样可能发生非标准行为……
[/Quote]
memset怎么会发生非标准行为? 这是标准C库函数吧~~~
另外boy前辈,我那个送给新手的帖子里,后面问了您几个问题,帮忙解答下吧~~
todo9351 2011-10-17
  • 打赏
  • 举报
回复
最好是用memset来清空吧。
Vincent_Song 2011-10-17
  • 打赏
  • 举报
回复
要用确定的方法,而不是依赖编译器以及未定义行为。
Qlaiaqu 2011-10-17
  • 打赏
  • 举报
回复
用bzero或者ZeroMomory
飞天御剑流 2011-10-17
  • 打赏
  • 举报
回复
对第一种初始化方式的担忧来源于某些编译器可能不会将后部的元素进行char()初始化,但我认为这种担忧是多余的,因为无论c还是c++,值初始化都是受标准支持的,都是标准明文规定的条款,对于内置类型,值初始化就是数值0,对于类,就是默认构造函数。

后部元素不进行值初始化就属于非标准行为了,不应该将非标准行为归咎于初始化方式,因为,如果将非标准行为归咎为原因的话,memset同样可能发生非标准行为。
ljhhh0123 2011-10-17
  • 打赏
  • 举报
回复
没有任何问题!否则请举出反例来。
quwei197874 2011-10-17
  • 打赏
  • 举报
回复
最好这样做
Enter空格 2011-10-17
  • 打赏
  • 举报
回复
呃。。
指定地址之后的指定长度,都被填充为指定的值。
Enter空格 2011-10-17
  • 打赏
  • 举报
回复
就像1楼说的。
{}是编译器实现的,好像没有规定说一个编译器实现{0}时,
必须使用0对buff缓冲区进行全部填充,所以可能会出现不同的行为。
而memset是标准C库函数,无论在哪个环境,这个函数实现的功能都是
设置目标缓冲区位指定长度的值。
ouyh12345 2011-10-17
  • 打赏
  • 举报
回复
当然需要用memset把所以成员都置为0
luciferisnotsatan 2011-10-17
  • 打赏
  • 举报
回复
char retbuff[100] = {0};
一般也就编译成

retbuff[0] = 0;
给第一个元素赋值
然后memset之后那99个元素
iamnobody 2011-10-17
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 qq120848369 的回复:]
有道理,{}是编译器问题,memset那就是个确定的函数。
[/Quote]

这个还是查一下标准吧。{};应该是默认构造函数吧。int();char()之类的都是0吧。
iamnobody 2011-10-17
  • 打赏
  • 举报
回复
用memset()不安全,如果不是char类型,又要计算他的大小。像这样:
memset(retbuff,0,100*sizeof(T));

如果你的retbuff是静态的,那么就应该memset();因为可能上次有人访问过它、
加载更多回复(1)

64,643

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧