char argv [] [7]和char*argv []之间的区别

Bry*_* K. 2 c c++

我最近学习了C语言.我读到有一些方法可以创建一个字符串数组.有什么区别char argv[][7]char *argv[]?如果没有你更喜欢使用的是什么?

aja*_*jay 5

引用C99标准§6.2.520(类型)

数组类型描述了具有特定成员对象类型的连续分配的非空对象集,称为元素类型.数组类型的特征在于它们的元素类型和数组中的元素数.

该标准在§6.2.522中进一步说明

未知大小的数组类型是不完整类型.对于该类型的标识符,通过在稍后的声明中指定大小(具有内部或外部链接)来完成.

数组下标运算符的[]优先级高于*运算符.因此,声明

char *argv[];
Run Code Online (Sandbox Code Playgroud)

argv由于未指定数组大小,因此将其定义为指向未知大小字符的指针数组.该数组argv是不完整的类型.这假设上述语句中的表达式不会显示为函数参数.由于数组argv是不完整类型,因此在使用之前必须提供其大小信息.这意味着您应该将上述语句作为声明并在其他地方提供其定义,以便链接器解析它.阅读本文,了解声明和定义之间的区别 -

定义和声明之间有什么区别?

// array declaration.
// this does not allocate space
// but only provides type information
// though of an incomplete type.
// argv must have internal or external linkage. 
extern char *argv[];

// definition of the array.
// complete information and
// allocates memory for it.
// in the same translation unit or 
// a different one.
char *argv[8];
Run Code Online (Sandbox Code Playgroud)

您还可以使用数组初始值设定项列表初始化数组,并从列表中推断出数组的大小.

// size of the array argv is determined
// explicitly to be 2
char *argv[] = {"Hello", "World"};

// the above is equivalent to
char *argv[2];
argv[0] = "Hello";
argv[1] = "World";
Run Code Online (Sandbox Code Playgroud)

注意:以上仅用于演示阵列初始化而不明确提及其大小.字符串文字是只读的,因此最好将该语句写为

const char *argv[] = {"Hello", "World"};
Run Code Online (Sandbox Code Playgroud)

如果它看起来像一个函数参数,那么它等同char **argv

int main(int argc; char *argv[]);
// equivalent to
int main(int argc, char **argv);
Run Code Online (Sandbox Code Playgroud)

以下语句中的数组也是如此.

char argv[][7];
Run Code Online (Sandbox Code Playgroud)

上面的语句定义argv为类型元素的数组char[7],即7字符数组.argv同样,未指定数组的大小.因此,argv是一种不完整的类型.假设它不作为函数参数出现,则应将该语句作为声明,因为它是一个不完整的类型,其定义应该在别处提供.

// array declaration.
// argv must have internal or external linkage
extern char argv[][7];

// definition.
// in the same translation unit
// or a different one
char argv[10][7];
Run Code Online (Sandbox Code Playgroud)

可以像前一种情况一样初始化数组,并且将从初始化列表中隐式确定大小.

// size of the array argv is inferred from 
// the initializer list to be 3.
char argv[][7] = {{'a', 'b', 'c', 'd', 'e', 'f', 'g'},
                  {'a', 'b', 'c', 'd', 'e', 'f', 'g'},
                  {'a', 'b', 'c', 'd', 'e', 'f', 'g'}};
Run Code Online (Sandbox Code Playgroud)

但是,如果数组表达式显示为函数参数,则它等效于
char (*)[7],即指向7字符数组的指针.

void foo(char argv[][7]);
// equivalent to
void foo(char (*)[7])
Run Code Online (Sandbox Code Playgroud)

这是因为您无法将数组传递给函数.实际传递的是指向数组第一个元素的指针.因此,函数中的数组参数将隐式转换为pointer to array elementtype.请阅读本文了解更多详情 -

为什么C和C++编译器在从未强制实施时允许函数签名中的数组长度?

  • 你应该补充一点,这个语法在声明时初始化时有意义. (2认同)
  • @MattMcNabb:这个问题被标记为C和C++.暂定定义是C特征,在C++中不存在(参见C++ 11附录§C.1.2,第一段).在每种情况下,或许可以清楚地区分各种语言,但正如我所看到的那样,问题应该归咎于...... (2认同)