【问题标题】:Why is the argument of main char **argv an array of Strings in c为什么 main char **argv 的参数是 c 中的字符串数组
【发布时间】:2018-10-29 10:20:38
【问题描述】:

在 c 的 main 函数中,这样的情况并不少见,

int main(int argc, char **argv){}

我对此有几个问题。这似乎是一个字符串数组,因为我可以访问argv[0] 并获取程序的名称,或者访问argv[1] 并获取一个正在传递给程序的参数。为什么char **argv 是一个字符串数组?我猜它是一个指向名为 argv 的 char 指针的指针。如果它不是一个字符串数组,那我为什么可以这样访问它。

【问题讨论】:

  • char **argv 一个字符串数组。
  • 在函数参数列表中,type *vartype var[]相同,所以char **argv等价于char *argv[],是一个字符串数组。
  • 参数存储在一个指针数组中。数组自然衰减为指向其第一个元素的指针。因此,如果您有一个指针数组,它将衰减为指向指针的指针。
  • 您可以使用指针的数组索引语法,因为像argv[i] 这样的表达式被语言视为指针算术。对于任何指针或数组p 和索引i,表达式p[i]*(p + i) 是相等的。

标签: c arrays pointers arguments main


【解决方案1】:

在 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 语言中仍然存在的规则是,当数组类型的值出现在表达式中时,它们会被转换为指向组成数组的第一个对象的指针。

【讨论】:

    猜你喜欢
    • 2011-08-14
    • 2014-01-10
    • 1970-01-01
    • 2015-04-25
    • 1970-01-01
    • 2015-11-07
    • 1970-01-01
    • 2015-09-06
    • 1970-01-01
    相关资源
    最近更新 更多