【发布时间】:2018-04-05 15:57:01
【问题描述】:
我今天与一位同事讨论了他(对我而言)不寻常的“主要”功能签名。他喜欢这样声明:
int main(int argc, char* (*argv)[]) {
printf("at index 0: %s\n", (*argv)[0]);
}
而我通常会写如下代码:
int main(int argc, char** argv)
{
printf("at index 0: %s\n", argv[0]);
}
有时我会写“char* argv[]”,以更清楚地表明 argv 是一个指向字符的指针数组。
第一个示例中的代码在编译时出现警告
warning: second argument of ‘main’ should be ‘char **’
但它有效。我的问题是为什么代码有效,因为我预计会由于取消引用 argv 而崩溃。编译器是否知道函数签名不同,并允许 (*argv) 在这里作为一种“无操作”?
为了了解发生了什么,我编写了以下示例,令我惊讶的是,它也没有崩溃并打印“first”(但编译器会发出警告):
#include <stdio.h>
int my_function(int argc, char* (*argv)[])
{
printf("at index 0: %s\n", (*argv)[0]);
}
int main(void)
{
char* stringArr[] = { "frist",
NULL };
size_t stringArrSz = sizeof(stringArr)/sizeof(*stringArr);
return my_function(stringArrSz, stringArr);
}
我曾预计我需要传递“&stringArr”(使用地址运算符)才能使代码运行。这 - 当然 - 也有效,并且修复了编译器警告。
如果我的问题不清楚,请告诉我,非常感谢任何帮助!
【问题讨论】:
-
请记住,对于函数参数,
[]被翻译为指针。所以char *argv[]真的是char **argv。现在想想char *(*argv)[]可能会被翻译成什么... -
另请注意,C 规范告诉
main的参数类型是什么。偏离这一点,您的程序将不再有效。我建议你阅读例如thismainfunction reference. -
@Someprogrammerdude 如果我没记错的话
char* (*argv)[]应该翻译成char*** argv。我不明白的是为什么取消引用 argv 仍然有效,即使在将 argv 传递给main时未使用运算符的地址。 -
@karacho84 - 您的评论与您的问题不同!哪一个是正确的?无论如何 -
char* (*argv)[]是错误的。警告类型告诉你。