我正在写一个C程序。它从commandLine获取它的参数。我想更改代码中的commandLine参数。由于它们被定义为“const char *”,我无法使用“strcpy”,“memcpy”来改变它们......还有,你知道,我不能只将它们的类型从“const char *”改为“char *” ”。 有没有办法改变它们?
提前非常感谢你。
祝你好运, 沙迪。
答案 0 :(得分:7)
根据C99§5.1.2.2.1/ 1,main
的签名是
int main(int argc, char *argv[]) { /* ... */ }
因此 允许删除const
。只是不要通过strcpy
比原始参数更长的字符串导致缓冲区溢出,或者尝试安装比最初传递的更多的参数。
其他人基本上都是正确的,你应创建副本。
答案 1 :(得分:2)
不,你不能修改它们。但是,没有规则禁止将它们复制到新缓冲区并使用它们。
答案 2 :(得分:1)
这可能不是重点,但你不能用strcpy()和memcpy()来改变任何东西;后缀'cpy'是复制的缩写(不出所料。)
关于更改argv指针,你当然可以改变指针,但为什么呢?如果您希望命令行参数不是给定的,请忽略它们,并使用您喜欢的任何值。另请注意,argv是一个参数,因此是main()的本地参数;如果在其他地方需要它,你必须将它作为参数传递,或者将其保存为全局变量。
答案 3 :(得分:0)
如果将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