在c的主要功能中,看到类似的东西并不罕见,
int main(int argc, char **argv){}
我对此有几个问题。看起来这是一个字符串数组,因为我可以访问argv[0]
并获取程序的名称,或访问argv[1]
并获取正在传递给程序的参数。为什么char **argv
是一个字符串数组?我猜它是一个指向名为argv的char指针的指针。如果它不是字符串数组,那么为什么我能够这样访问它。
答案 0 :(得分:2)
在C中,当在大多数表达式中使用数组的名称时,表达式中使用的值是数组的第一个元素的地址,其类型是指向该元素类型的指针。当数组传递给函数时,这仍然是正确的。所以,即使C的语法允许你声明:
void foo(int x[]);
x
所拥有的类型不是int
的数组,而是指向int
的指针。所以,它实际上与:
void foo(int *x);
对于main
,这意味着:
int main(int argc, char *argv[]);
实际上与:
相同int main(int argc, char **argv);
允许数组名称“衰减”为指针类型是为C的新类型功能唯一创建的功能,以保持与C的无类型前辈的向后兼容性。来自The Development of the C Language
...例如,早期Unix系统的目录条目可能在C中描述为
struct { int inumber; char name[14]; };
我希望结构不仅可以表征抽象对象,还可以描述可能从目录中读取的位集合。编译器在哪里可以隐藏指向语义要求的名称的指针?即使结构被认为更抽象,并且指针的空间可能以某种方式隐藏,我如何处理在分配复杂对象时正确初始化这些指针的技术问题,也许是指定包含包含任意深度结构的数组的结构?
该解决方案构成了无类型BCPL和类型C之间的进化链中的关键跳跃。它消除了存储中指针的具体化,而在表达式中提到数组名称时导致了指针的创建。在今天的C中幸存的规则是,数组类型的值在表达式中出现时转换为指向构成数组的第一个对象的指针。