如何处理argv字符数组赋值?

时间:2009-07-31 18:58:24

标签: c argv

我找到了两种将命令行参数传递给字符数组的方法:

int main (int argc, char **argv)
{
  const char *s1 = argv[0];
  char s2[256];
  strcpy(s2, argv[0]);

  printf("s1: %s\ns2: %s\n\n", s1, s2);
}

在AIX系统上使用IBM xlc编译器进行编译返回

  

[MyPrompt] GT; ./a.out

     

s1:./ a.out

     

s2:./ a.out

哪个实现(s1或s2)是正确的? s1很好,因为argv [0]可以是任何长度。 s2要求argv [0]的长度<1。 256个字符。

我不明白s1应该如何/为什么应该起作用。我认为在编译时应该需要s1的右侧,但我认为它是在运行时生成的。

6 个答案:

答案 0 :(得分:3)

s1起作用的原因是因为argv [0] 的类型是指针。您只需分配地址(而不是实际值),这是安全的。您没有进行任何类型的分配或演员。

我通常更喜欢第一个选项,因为您应该只读取参数变量。

答案 1 :(得分:3)

如果您不想更改字符串,那么s1将起作用。

如果您想更改字符串,则可以复制它。如果你的系统支持它,你应该使用更安全的strnlen()和strncpy()。

答案 2 :(得分:1)

  

我认为s1的右侧   应该在编译时需要,   但我认为它是由...产生的   运行时间。

不,每次遇到语句都需要它。例如:

void f() {
   int x = 1;
   ...
}

每次调用函数时,整数x都将初始化为1,而不是在编译时。

答案 3 :(得分:1)

s2具有易受缓​​冲区溢出影响的令人愉快的特性。

我看到人们改变了argv [0]的值。在某些情况下,(在某些操作系统上)更改argv [0]会使程序显示为ps,就像你改变它一样。

答案 4 :(得分:0)

如果您只想引用参数而不对其进行任何更改,则 s1 是正确的。

如果您需要以任何方式修改参数,那么您需要像 s2 示例中那样复制它,但在 s2 示例中,您需要明确检查查看长度是否比您要复制到的缓冲区长。例如,如果您正在使用像filename.jpg这样的参数作为输入并保存filename.gif作为输出,那么您需要复制该参数,因为您将把扩展名从.jpg更改为.gif

答案 5 :(得分:0)

我会选择s1,特别是对于argv [n],其中n&gt;像s2这样的东西打开你的经典缓冲区溢出攻击。基本上,用户可以格式化长度超过256个字符的参数并覆盖堆栈上的信息,以便它们可以运行他们想要的任何代码。