【问题标题】:changing command line arguments更改命令行参数
【发布时间】:2010-04-16 17:25:19
【问题描述】:

我正在编写一个 C 程序。它从命令行获取参数。我想更改代码中的命令行参数。因为它们被定义为“const char *”,所以我无法使用“strcpy”、“memcpy”等来更改它们……另外,你知道,我不能只将它们的类型从“const char *”更改为“char * ”。 有什么办法可以改变它们吗?

非常感谢您。

最好的问候, 沙迪。

【问题讨论】:

  • 为什么需要更改命令行参数?如果您正在修改它们以传递到程序的另一部分,您可能需要复制并修改它。
  • 你有没有想过将参数复制到不同的变量并使用它?

标签: c command-line


【解决方案1】:

根据 C99 §5.1.2.2.1/1,main 的签名是

int main(int argc, char *argv[]) { /* ... */ }

所以你被允许删除const。只是不要让strcpying 在比原始参数更长的字符串中导致缓冲区溢出,或者尝试安装比最初传递的更多的参数。

其他人基本上是对的,您应该创建一个副本。

【讨论】:

  • C 没有的那些很棒的字符串向量之一? ;-)
  • @James:rofl,适合我一次处理太多问题。
  • 甚至不仅仅是您可能从参数类型中推断出的内容,该标准还明确规定:“参数 argc 和 argv 以及 argv 数组指向的字符串应由程序修改.. 。”
【解决方案2】:

不,您不能修改这些。但是,没有规则禁止将它们复制到新缓冲区并使用它们。

【讨论】:

    【解决方案3】:

    这可能是题外话,但是你不能用 strcpy() 和 memcpy() 改变任何东西;后缀“cpy”是复制的缩写(不出所料。)

    关于更改 argv 指针,当然可以更改指针,但为什么呢?如果您希望命令行参数不是给定的,只需忽略它们,并使用您喜欢的任何值。另请注意, argv 是一个参数,因此是 main() 的本地参数;如果在其他地方需要它,您必须将其作为参数传递,或者将其保存为全局变量。

    【讨论】:

    • 重新。 “你不能用strcpy()改变任何东西”;如果它没有改变任何东西,那将毫无意义。如果你做strcpy(argv[0], "foo");,它会改变argv[0]的(内容)。
    【解决方案4】:

    把 const char * 改成 main 函数的 char * 也没关系。

    您必须关心的只有一件事是 strcpy 的缓冲区溢出。

    根据ELF规范(见图3-31堆栈布局),http://refspecs.linuxbase.org/elf/abi386-4.pdf,函数参数区后面是环境值区。

    argv 是指向每个参数的指针数组,environ 也是指向每个环境 var=value 字符串的指针数组。 所以布局如下。

    argv[0]  --> 1st parameter
    argv[1]  --> 2nd parameter
    argv[2]  --> 3rd parameter
    ...
    NULL
    --------------------------------------- memory boundary between param and env
    environ[0] --> 1st env_var=env_value
    environ[1] --> 2nd env_var=env_value
    environ[2] --> 3rd env_var=env_value
    ...
    NULL
    

    因此,如果您将很长的字符串复制到 argv[0],它可能会超出 param 和 env 之间的边界。 在这种情况下,您必须将 argv 和 environ 内存区域移动到另一个堆空间,如下所示。 我从 Postgresql 开源代码中提取了下面的示例代码。 ps_status.c)

    char ** new_environ;
    char ** new_argv;
    char ** org_argv;
    int     i;
    
    new_argv = (char **) malloc((argc + 1) * sizeof(char *));
    for (i = 0; i < argc; i++)
        new_argv[i] = strdup(argv[i]);
    new_argv[argc] = NULL;
    org_argv = argv;
    argv = new_argv;
    
    new_environ = (char **) malloc((i + 1) * sizeof(char *));
    for (i = 0; environ[i] != NULL; i++)
        new_environ[i] = strdup(environ[i]);
    new_environ[i] = NULL;
    environ = new_environ;
    

    然后,您可以使用 getopt、getenv 等。 他们将从新分配的内存区域读取值。 此外,如果您更改原始参数(org_argv[0]),您可以在 ps 命令中操作进程的输出名称。 (也在顶部,htop 实用程序中) 见下文。

    $> ps -ef | grep my_proc
      dplee 10855 1 0 7월28 pts/2 00:00:16 my_proc i can manipulate this name
    

    【讨论】:

      猜你喜欢
      • 2013-06-13
      • 1970-01-01
      • 2016-03-17
      • 1970-01-01
      • 2011-06-17
      • 2014-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多