我找到了两种将命令行参数传递给字符数组的方法:
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的右侧,但我认为它是在运行时生成的。
答案 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个字符的参数并覆盖堆栈上的信息,以便它们可以运行他们想要的任何代码。