为什么在这种情况下使用memset

时间:2019-11-02 12:32:23

标签: c

我已经从退休的以前的开发人员那里继承了一些代码。我的问题是在以下情况下专门使用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]);
}

4 个答案:

答案 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

可以看出结果不是预期的。现在,数组包含一组三个字符串,而不是一个字符串。