[英]Why use memset in this case
我从以前退休的开发人员那里继承了一些代码。 我的问题具体是在以下场景中使用 memset。 不是 c 程序员,我想知道为什么在这种特殊情况下使用 memset,下一行代码将值存储在 memset 刚刚设置为全 0 的变量中。 是否有理由在 strcpy 之前使用 memset?
switch(argc)
{
case 1 :
printf("\nCommand: %s \n",argv[0]);
break;
case 2 :
memset(program_input_string,0,sizeof(program_input_string));
strcpy(program_input_string,argv[1]);
printf("\nCommand: %s [%s] \n",argv[0],argv[1]);
break;
default :
printf("\nCommand: %s \n",argv[0]);
}
事实上,在这种情况下使用memset
+ strcpy
的理由为零。 事实上,如果程序员想要确保剩余的字节被清零,那么应该使用带有条件的strncpy
来测试字符串是否完全适合缓冲区:
strncpy(program_input_string, argv[1], sizeof program_input_string);
// if the last character in the array is not '\0', it means that the
// string did not fit into the array in its entirety, and perhaps
// the only sensible course of action is to abort the program...
if (program_input_string[sizeof program_input_string - 1] != '\0') {
fputs("The argument was too long!", stderr);
exit(1);
}
这有两个明显的优点:它不会将初始序列不必要地设置为零,并且它不会溢出输入缓冲区 - 如果缓冲区溢出发生,它将退出并显示合理的错误消息和退出代码。
因此,对“为什么使用这种结构”这个问题的明确答案将是非常常见的“程序员无能”。
这可能是不必要的,但您应该在删除它之前仔细检查。
memset()
确保终端\0
之后的任何字节都被清零。 如果program_input_string
始终被读取为字符串,并且代码在到达\0
时始终停止,那么后面的内容并不重要。
如果有从整个缓冲区读取的代码(包括尾随字节),这可能会很有用。 例如,如果所有sizeof(program_input_string)
字节都被复制到网络数据包中并通过网络发送,您就不想传输未初始化的字节。 在这种情况下,将缓冲区归零是值得的。
我想知道为什么在这种特殊情况下使用 memset,下一行代码将值存储在 memset 刚刚设置为全 0 的变量中。 是否有理由在 strcpy 之前使用 memset?
提供的特定memset()
调用将目标数组的每个字节设置为 0。 strcpy()
调用成功后,仅覆盖argv[1]
字符串中的字节数,包括可能更少的终止符。 这种区别实际上对程序是否重要,无法从提供的代码中确定。
另请注意,所提供的代码可能会出现缓冲区溢出——它实际上是该问题的典型案例之一。 如果argv[1]
比目标数组长,则会出现未定义的行为。
在这种情况下,调用 memset 是多余的。 你可以写
strcpy(program_input_string,argv[1]);
因为 function strcpy 也会复制目标字符串中的终止零。
作为一个想法,有时一个字符数组需要包含几个字符串。 在这种情况下,两个连续的零表示存储在字符数组中的字符串集的结尾。 所以需要用零初始化数组。
假设数组program_input_string
已经包含字符串
ABC\0DEF\0\0
那么如果复制字符串 E 你会得到
E\0C\0DEF\0\0
正如所见,结果不是预期的。 现在数组包含一组三个字符串而不是一个字符串。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.