如何使用memcpy将指针复制到数组的元素

时间:2015-05-15 02:54:01

标签: c arrays pointers memcpy

执行此代码后:

char **argv_p;
char *argv[20] = { NULL };

memcpy(&argv_p, &argv, sizeof(argv_p));

argv_p最终为NULL。

这是因为& argv正在分解为指向argv数组中第一个指针的指针。使用&argv[0]会产生相同的结果(如预期的那样)。

问题是,C中是否存在允许将char ***传递给memcpy的语法,而不会诉诸像hacky这样的东西

char **argv_p;
char *argv[20] = { NULL }, **argv_start = argv;

memcpy(&argv_p, &argv_start, sizeof(argv_p));

我测试过并产生了正确的结果。

编辑:我知道你可以直接分配,但这是为了解决const问题。如果有人知道为什么execve采用char * const *而不是char const **作为其第二个参数,则可以获得互联网积分。

修改编辑:为了澄清,有争议的区别:

char * const * - 使数组的内容不可变 char const ** - 使数组指向的字符串缓冲区的内容为immutable。

Const总是恭维左边的东西,除非它首先出现(ANSI C的家伙需要射击),在这种情况下它会在右边的东西上作出判断。虽然很多人写const char *,但有些人认为最好的做法是编写char const *,因为const的应用是一致的。

如果没有收到C编译器的警告,你就不能抛弃const。 memcpy是在没有警告的情况下解决此问题的唯一方法。

许多较旧的库没有正确地将其函数的参数标记为const,如果已将const正确应用于代码中的类型,则编译器将发出警告。这就是使用memcpy偶尔可以接受的原因。

2 个答案:

答案 0 :(得分:0)

不要尝试通过复制指针来解决const

相反,可能需要复制指针所指向的数据,然后您可以使用非const指针指向非const数据,并且所有这些数据都适用于编译器和优化器。

别名指针以避免使用限定符永远不会被接受,无论如何完成,即将指针复制到具有不同限定符的变量甚至不是好习惯,在某些情况下甚至可能导致运行时错误或其他未定义的行为(例如,在const限定符导致引用的存储为只读,并且别名(ab)用于尝试实际修改存储的情况下。

应尽可能删除限定符"上游"避免与可能不接受带限定符的参数的系统库造成不必要的冲突(C当然并不总是允许这种可能性)。

在绝对必要的地方,以及可以证明不会导致问题的地方,可以使用__UNCONST()宏。如果目标平台的编译器没有提供,那么最好的解决方案是将__UNCONST()定义为无操作,并记录可能导致可能接受的潜在警告(并说明原因)。

答案 1 :(得分:0)

在execve中,argv可以声明为char *const argv[]并向后读取它是一个常量字符串数组,但该数组是可变的,可以更改为包含不同的常量字符串。在老式的Unix系统中,C main函数可以带3个参数,第三个参数就像execve一样是环境数组。在main()中,如果你正确地修改了argv(例如,将元素设置为"",直到你遇到终止NULL),你可以阻止ps命令显示已传递给它的命令行参数你的计划。通过设置argv[0]="foo",命令将显示为" foo"是可执行文件的名称。例如,如果您的命令将密码作为命令行参数,那么在新奇的Linux系统上将其隐藏起来ps/proc/PID/cmdline是明智的。有关如何在新奇的Linux系统中执行相同操作,请参阅http://netsplit.com/hiding-arguments-from-ps