当我看到
时,我正在研究linux C ++编程int execve(const char *path,
char *const argv[],
char *const envp[]);
我不明白什么是char *const argv[]
。我知道char *const foo
是一个指向char的const指针。 const char *foo
是指向const char的指针。但是什么是char *const argv[]
?
是char的const指针数组还是const char的指针数组?
我现在有vector<string>
,如何将其转换为char *const argv[]
?
答案 0 :(得分:31)
是char的const指针数组还是const char的指针数组?
从右到左阅读类型:
const总是绑定到左边(除非它在最左边)
char *const argv[]
^^ Array of
^^^^^ const
^ pointer to
^^^^ char
"const pointer"
到char
因此无法修改数组中的指针 但他们指出的可以修改。
注意:正如史蒂夫在下面指出的那样。因为这被用作参数。它实际上衰落为“指向"const pointer"
to char”或“char * const *”的指针。
我有一个矢量&lt; string&gt;现在,如何将其转换为char * const argv []?
int execve(const char *path,
char *const argv[],
char *const envp[]);
int main()
{
std::vector<std::string> data; /// fill
std::vector<char*> argv;
std::vector<char*> envp;
for(std::vector<std::string>::iterator loop = data.begin(); loop != data.end(); ++loop)
{
argv.push_back(&(*loop)[0]);
}
// I also bet that argv and envp need to be NULL terminated
argv.push_back(NULL);
envp.push_back(NULL);
execve("MyAppName", &argv[0], &envp[0]);
}
答案 1 :(得分:2)
char *const argv[]
将
的argv
声明为指向const
char
数组
答案 2 :(得分:1)
// says: argv is a constant pointer pointing to a char*
int main(int c, char *const argv[]);
您将无法在功能中更改“argv”。
由于你刚刚学习C语言,我建议你首先尝试理解数组和指针之间的差异,而不是常见的事情。
在参数和数组领域,有一些令人困惑的规则应该在继续之前清楚。首先,您在参数列表中声明的内容将被视为特殊内容。在某些情况下,事物在C中作为函数参数没有意义。这些是
数组作为参数
第二个可能不会立即清楚。但是当你认为数组维度的大小是C中类型的一部分时(而且没有给出维度大小的数组具有不完整的类型),就会变得很清楚。因此,如果您要创建一个采用数组按值(接收副本)的函数,那么它只能用于一个大小!此外,数组可能会变大,而C会尽可能快。
在C中,由于这些原因,不存在数组值。如果要获取数组的值,则获得的是指向该数组的第一个元素的指针。而这里实际上已经是解决方案了。 C编译器不会在前面绘制数组参数,而是将相应参数的类型转换为指针。记住这一点,这非常重要。该参数不是数组,而是指向相应元素类型的指针。
现在,如果你尝试传递一个数组,那么传递的是指向数组第一个元素的指针。
游览:作为参数的功能
为了完成,并且因为我认为这将有助于您更好地理解这个问题,让我们看看当您尝试将函数作为参数时的状态。的确,首先它没有任何意义。参数如何成为函数?嗯,当然,我们想要一个变量!那么编译器在发生这种情况时所做的就是将函数转换为函数指针。尝试传递函数将传递指向相应函数的指针。所以,以下是相同的(类似于数组示例):
void f(void g(void));
void f(void (*g)(void));
请注意,需要*g
周围的括号。否则,它将指定一个返回void*
的函数,而不是指向返回void
的函数的指针。
返回数组
现在,我在开始时说过,数组可能有一个不完整的类型 - 如果你还没有给出一个大小,就会发生这种情况。由于我们已经认为数组参数不存在,而是任何数组参数都是指针,因此数组的大小无关紧要。这意味着,编译器将翻译以下所有内容,并且所有内容都是相同的:
int main(int c, char **argv);
int main(int c, char *argv[]);
int main(int c, char *argv[1]);
int main(int c, char *argv[42]);
当然,能够在其中放置任何尺寸并没有多大意义,它只是扔掉了。出于这个原因,C99为这些数字提出了新的含义,并允许在括号之间出现其他内容:
// says: argv is a non-null pointer pointing to at least 5 char*'s
// allows CPU to pre-load some memory.
int main(int c, char *argv[static 5]);
// says: argv is a constant pointer pointing to a char*
int main(int c, char *argv[const]);
// says the same as the previous one
int main(int c, char ** const argv);
最后两行表示你将无法在函数中更改“argv” - 它已成为const
指针。但是只有少数C编译器支持这些C99功能。但是这些特征清楚地表明“阵列”实际上并不是一个。这是一个指针。
警告
请注意,只有当您将数组作为函数的参数时,我所说的才是真的。如果使用本地数组,则数组将不是指针。它将表现为指针,因为如前所述,数组在读取其值时将转换为指针。但它不应该与指针混淆。
一个典型的例子如下:
char c[10];
char **c = &c; // does not work.
typedef char array[10];
array *pc = &c; // *does* work.
// same without typedef. Parens needed, because [...] has
// higher precedence than '*'. Analogous to the function example above.
char (*array)[10] = &c;