Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么'execv'可以';是否使用从字符**到字符*常量*的隐式转换?_C_Execv - Fatal编程技术网

为什么'execv'可以';是否使用从字符**到字符*常量*的隐式转换?

为什么'execv'可以';是否使用从字符**到字符*常量*的隐式转换?,c,execv,C,Execv,考虑以下代码: #include <stdio.h> #include <unistd.h> void foo(char * const arg[]) { printf("success\n"); } int main() { char myargs[2][64] = { "/bin/ls", NULL }; foo(myargs); execv(myargs[0], myargs); return 0; } #包括 #包括

考虑以下代码:

#include <stdio.h>
#include <unistd.h>

void foo(char * const arg[]) {
    printf("success\n");
}

int main() {
    char myargs[2][64] = { "/bin/ls", NULL };

    foo(myargs);
    execv(myargs[0], myargs);
    return 0;
}
#包括
#包括
void foo(字符*常量参数[]){
printf(“成功”\n);
}
int main(){
char myargs[2][64]={“/bin/ls”,NULL};
foo(myargs);
execv(myargs[0],myargs);
返回0;
}
foo
execv
都需要
char*const*
参数,但是当我的
foo
工作时(我在输出中获得
success
),系统调用
execv
失败

我想知道为什么。这是否与
execv
的实现有关


另外,假设我有一个
char**
变量-如何将其发送到
execv

二维数组如下所示:

char myargs[2][16];

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
char myargs[2][16] = { "/bin/ls", "" }

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
void foo(char (*arg)[16]);
...
char myargs[2][16] = { "/bin/ls", "" }
foo(myargs);

+-----------+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  POINTER==|===>| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+-----------+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
我将图表的大小从64减少到16,以避免图表过于庞大

使用初始值设定项时,它可以如下所示:

char myargs[2][16];

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
char myargs[2][16] = { "/bin/ls", "" }

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
void foo(char (*arg)[16]);
...
char myargs[2][16] = { "/bin/ls", "" }
foo(myargs);

+-----------+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  POINTER==|===>| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+-----------+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
请注意,我没有尝试在第二行中放置空指针。这样做没有意义,因为这是一个字符数组。里面没有放指针的地方

这些行在内存中是连续的,因此如果您查看较低级别,实际上更像这样:

char myargs[2][16];

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
char myargs[2][16] = { "/bin/ls", "" }

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
void foo(char (*arg)[16]);
...
char myargs[2][16] = { "/bin/ls", "" }
foo(myargs);

+-----------+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  POINTER==|===>| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+-----------+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
myargs
传递给函数时,著名的“数组衰减”会生成指针。看起来是这样的:

char myargs[2][16];

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
char myargs[2][16] = { "/bin/ls", "" }

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
void foo(char (*arg)[16]);
...
char myargs[2][16] = { "/bin/ls", "" }
foo(myargs);

+-----------+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  POINTER==|===>| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+-----------+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
指针为
arg
包含一个位于数组开头的值。请注意,没有指向第二行的指针。如果
foo
想要在第二行中找到值,它需要知道行有多大,以便能够分解以下内容:

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
为此:

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
这就是为什么
arg
必须是
char(*arg)[16]
而不是
char**arg
或等效的
char*arg[]

exec
函数系列不适用于此数据布局。它想要这样:

+-----------+    +-----------+-----------+
|  POINTER==|===>|  POINTER  |    NULL   |
+-----------+    +-----|-----+-----------+
                       |
/----------------------/
|
|
|    +--+--+--+--+--+--+--+--+
\--->| /| b| i| n| /| l| s|\0|
     +--+--+--+--+--+--+--+--+
+-----------+    +-----------+-----------+-   -+-----------+
|  POINTER==|===>|  POINTER  |  POINTER  | ... |    NULL   |
+-----------+    +-----|-----+-----|-----+-   -+-----------+
                       |           |
/----------------------/           |
|                                  |
| /--------------------------------/
| |
| |
| |  +--+--+--+--+--+--+--+--+
\-+->| /| b| i| n| /| l| s|\0|
  |  +--+--+--+--+--+--+--+--+
  |
  |  +--+--+--+--+--+--+
  \->| /| h| o| m| e|\0|
     +--+--+--+--+--+--+
当您想要添加更多参数时,它需要:

+-----------+    +-----------+-----------+
|  POINTER==|===>|  POINTER  |    NULL   |
+-----------+    +-----|-----+-----------+
                       |
/----------------------/
|
|
|    +--+--+--+--+--+--+--+--+
\--->| /| b| i| n| /| l| s|\0|
     +--+--+--+--+--+--+--+--+
+-----------+    +-----------+-----------+-   -+-----------+
|  POINTER==|===>|  POINTER  |  POINTER  | ... |    NULL   |
+-----------+    +-----|-----+-----|-----+-   -+-----------+
                       |           |
/----------------------/           |
|                                  |
| /--------------------------------/
| |
| |
| |  +--+--+--+--+--+--+--+--+
\-+->| /| b| i| n| /| l| s|\0|
  |  +--+--+--+--+--+--+--+--+
  |
  |  +--+--+--+--+--+--+
  \->| /| h| o| m| e|\0|
     +--+--+--+--+--+--+

如果您将其与二维数组图进行比较,希望您能够理解为什么这不能是隐式转换。它实际上包括在内存中移动内容。

二维数组如下所示:

char myargs[2][16];

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
char myargs[2][16] = { "/bin/ls", "" }

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
void foo(char (*arg)[16]);
...
char myargs[2][16] = { "/bin/ls", "" }
foo(myargs);

+-----------+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  POINTER==|===>| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+-----------+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
我将图表的大小从64减少到16,以避免图表过于庞大

使用初始值设定项时,它可以如下所示:

char myargs[2][16];

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
char myargs[2][16] = { "/bin/ls", "" }

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
void foo(char (*arg)[16]);
...
char myargs[2][16] = { "/bin/ls", "" }
foo(myargs);

+-----------+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  POINTER==|===>| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+-----------+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
请注意,我没有尝试在第二行中放置空指针。这样做没有意义,因为这是一个字符数组。里面没有放指针的地方

这些行在内存中是连续的,因此如果您查看较低级别,实际上更像这样:

char myargs[2][16];

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
char myargs[2][16] = { "/bin/ls", "" }

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
void foo(char (*arg)[16]);
...
char myargs[2][16] = { "/bin/ls", "" }
foo(myargs);

+-----------+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  POINTER==|===>| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+-----------+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
myargs
传递给函数时,著名的“数组衰减”会生成指针。看起来是这样的:

char myargs[2][16];

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
char myargs[2][16] = { "/bin/ls", "" }

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
void foo(char (*arg)[16]);
...
char myargs[2][16] = { "/bin/ls", "" }
foo(myargs);

+-----------+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  POINTER==|===>| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+-----------+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
指针为
arg
包含一个位于数组开头的值。请注意,没有指向第二行的指针。如果
foo
想要在第二行中找到值,它需要知道行有多大,以便能够分解以下内容:

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
为此:

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0|  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|\0|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
这就是为什么
arg
必须是
char(*arg)[16]
而不是
char**arg
或等效的
char*arg[]

exec
函数系列不适用于此数据布局。它想要这样:

+-----------+    +-----------+-----------+
|  POINTER==|===>|  POINTER  |    NULL   |
+-----------+    +-----|-----+-----------+
                       |
/----------------------/
|
|
|    +--+--+--+--+--+--+--+--+
\--->| /| b| i| n| /| l| s|\0|
     +--+--+--+--+--+--+--+--+
+-----------+    +-----------+-----------+-   -+-----------+
|  POINTER==|===>|  POINTER  |  POINTER  | ... |    NULL   |
+-----------+    +-----|-----+-----|-----+-   -+-----------+
                       |           |
/----------------------/           |
|                                  |
| /--------------------------------/
| |
| |
| |  +--+--+--+--+--+--+--+--+
\-+->| /| b| i| n| /| l| s|\0|
  |  +--+--+--+--+--+--+--+--+
  |
  |  +--+--+--+--+--+--+
  \->| /| h| o| m| e|\0|
     +--+--+--+--+--+--+
当您想要添加更多参数时,它需要:

+-----------+    +-----------+-----------+
|  POINTER==|===>|  POINTER  |    NULL   |
+-----------+    +-----|-----+-----------+
                       |
/----------------------/
|
|
|    +--+--+--+--+--+--+--+--+
\--->| /| b| i| n| /| l| s|\0|
     +--+--+--+--+--+--+--+--+
+-----------+    +-----------+-----------+-   -+-----------+
|  POINTER==|===>|  POINTER  |  POINTER  | ... |    NULL   |
+-----------+    +-----|-----+-----|-----+-   -+-----------+
                       |           |
/----------------------/           |
|                                  |
| /--------------------------------/
| |
| |
| |  +--+--+--+--+--+--+--+--+
\-+->| /| b| i| n| /| l| s|\0|
  |  +--+--+--+--+--+--+--+--+
  |
  |  +--+--+--+--+--+--+
  \->| /| h| o| m| e|\0|
     +--+--+--+--+--+--+
如果您将其与二维数组图进行比较,希望您能够理解为什么这不能是隐式转换。它实际上包括在内存中移动东西

foo
execv
都需要
char*const*
参数

但是,当我的
foo
工作时(我在输出中获得成功),系统调用
execv
失败

获得您期望的输出并不能证明您的代码是正确的。调用表现出未定义的行为,因为它的参数与参数类型不匹配,但这似乎没有什么实际效果,因为
foo()
的实现没有以任何方式使用参数。更一般地说,原则上,您的代码完全可以显示任何行为,因为这就是“未定义”的含义

我想知道为什么。这是否与
execv
的实现有关

从标准的角度来看,两个调用都表现出相同的未定义行为。但是,实际上,我们知道,
execv
确实使用了它的参数,因此该调用产生您期望的行为比调用
foo
产生您期望的行为更令人惊讶

主要问题是,而且。因此,您的2D数组
myargs
对于任何函数的参数都没有正确的类型

另外,假设我有一个char**变量,我如何将它发送到execv

代码中没有这样的变量,但如果有,可以将其转换为适当的类型:

char *some_args[] = { "/bin/ls", NULL };
execv((char * const *) some_args);
实际上,如果您也省略了强制转换,大多数编译器可能也会接受它,尽管标准确实要求这样做。最好首先声明一个类型正确的变量:

char * const correct_args[] = { "/bin/ls", NULL };
execv(correct_args);
还要注意的是,尽管数组不是指针,但它们在大多数上下文(我在示例代码中使用)中都转换为指针,但仅在顶层。因此,数组数组“衰减”为指向数组的指针,而不是指向指针的指针

foo
execv
都需要
char*const*
参数

但是,当我的
foo
工作时(我在输出中获得成功),系统调用
execv
失败

获得您期望的输出并不能证明您的代码是正确的。调用显示未定义的行为,因为它的参数与参数类型不匹配,但这似乎没有什么实际效果,因为
foo()
的实现没有使用参数