2011-08-11 118 views
11

我学习linux的C++编程,当我看到什么是char * const argv []?

int execve(const char *path, 
      char *const argv[], 
      char *const envp[]); 

我不明白什么是char *const argv[]。我知道char *const foo是一个char指针。而const char *foo是一个指向const char的指针。但是什么是char *const argv[]

它是一个char指针数组或指向const char的指针数组的数组指针?

而我现在有一个vector<string>,如何将其转换为char *const argv[]

回答

28

它是常量指针数组为char或指针数组为const char ?

阅读类型从右至左:
常量总是结合向左(除非是在最左边),

char *const argv[] 

       ^^ Array of 
     ^^^^^  const 
    ^   pointer to 
^^^^    char 

"const pointer"数组为char

所以三分球该数组不能修改。
但他们指出可以修改。

注意:正如下面的史蒂夫指出的那样。因为这被用作参数。它实际上衰减到“指向"const pointer" char”或“char * const *”的指针。

我有一个向量<字符串>现在,如何将它转换为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]); 
} 
+2

+1为图解说明:D – Nawaz

+3

确实'char * const argv []'是一个数组类型,但在这个上下文中,函数参数的类型不是'char * const argv []',它是'char * const * argv'。 –

2

cdecl.org说:

char *const argv[] 

声明argv作为const指针的数组char

+0

和如何转换'矢量''到char * const的的argv []'? – Kaoet

+1

也有用:http://www.unixwiz.net/techtips/reading-cdecl.html –

+0

@MrPhone:也许作为一个单独的问题发布。这很简单,但写出来需要的不仅仅是评论。 –

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; 
+0

不知道为什么这是今天downvoted – 2013-02-20 13:47:20

相关问题