我已经从退休的以前的开发人员那里继承了一些代码。我的问题是在以下情况下专门使用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]);
}
答案 0 :(得分:3)
事实是在这种情况下使用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);
}
这有两个明显的优点:它不会将初始序列不必要地设置为零 它不会溢出输入缓冲区-如果缓冲区溢出会发生将退出并显示一条错误消息并退出代码。
因此,“为什么要使用这种结构”这个问题的明确答案将是“程序员无能”。
答案 1 :(得分:2)
可能 是不必要的,但是在删除之前应仔细检查。
memset()
确保将终端\0
之后的所有字节清零。如果program_input_string
始终被读取为字符串,并且在命中\0
时代码总是停止,那么之后的结果无关紧要。
如果有从整个缓冲区读取的代码(包括尾随字节),则可能会很有用。例如,如果将所有sizeof(program_input_string)
个字节复制到网络数据包中并通过电线发送,则您将不希望传输未初始化的字节。在这种情况下,将缓冲区清零是值得的。
答案 2 :(得分:1)
我想知道为什么在这种特殊情况下使用memset,下一行代码将值存储在刚刚由memset设置为全0的变量中。有没有理由在strcpy之前使用memset?
提出的特定memset()
调用将目标数组的每个字节设置为0。strcpy()
调用成功后,只会覆盖{ {1}}字符串,包括终止符,可能更少。从所提供的代码中无法确定这种区别对程序实际上是否重要。
还请注意,所提供的代码可能会缓冲区溢出-实际上,这是该问题的一种典型案例。如果argv[1]
比目标数组长 ,则会发生未定义的行为。
答案 3 :(得分:0)
在这种情况下,调用memset是多余的。你可能只是写
strcpy(program_input_string,argv[1]);
因为strcpy函数还复制了目标字符串中的终止零。
作为一个主意,有时字符数组需要包含多个字符串。在这种情况下,两个相应的零表示存储在字符数组中的字符串集的结尾。因此,需要使用零初始化数组。
我们假设数组program_input_string
已包含字符串
ABC\0DEF\0\0
然后如果要复制字符串E,您将得到
E\0C\0DEF\0\0
可以看出结果不是预期的。现在,数组包含一组三个字符串,而不是一个字符串。