为什么sizeof(argv)/ sizeof(argv [0])在C++中给出了数组的大小?

get*_*nge 3 c++ arrays pointers sizeof

如果我在main中有一个数组作为参数

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

为什么会

sizeof(argv)/sizeof(argv[0])
Run Code Online (Sandbox Code Playgroud)

总能可靠地给我阵列的长度?

Kei*_*son 21

它没有.

在写这个答案时,我可能会有点失望; 对于一个相当简单的问题,语言 - 律师方法太过分了.我将添加这个快速摘要,足以回答这个问题.答案的迂腐和过于冗长的版本低于水平线.

鉴于:

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

argv根本不是一个数组; 它是一个指针.(C和C++不允许数组类型的参数;看起来像数组参数的东西实际上是一个指针参数.)argv确实指向(在运行时)数组的第一个元素,但是声明中没有关于这个数组有多大.这就是我们需要argc参数来提供该信息的原因.

所以sizeof(argv)/sizeof(argv[0]) 给你数组中的元素数量; 它只是将指针的大小除以指针的大小,这可能会给你1.(为什么只有"可能"?这是下面过于迂腐的答案的一部分.)

现在,如果您将某些内容显式定义为数组对象:

int an_array[42];
Run Code Online (Sandbox Code Playgroud)

可以用这个成语来计算数组中元素的数量:

sizeof an_array / sizeof an_array[0]
Run Code Online (Sandbox Code Playgroud)

这产生42了数组中元素的数量.它的工作方式(我认为)非常简单:它是整个数组的字节大小除以其中一个元素的字节大小.

但是,它的工作原理只是一个实际的数组,而不是像argv那个看起来像一个数组,但确实是一个指针.

数组和指针之间的关系可能令人困惑.comp.lang.c FAQ的第6节很好地解释了它,大部分或全部适用于C和C++.

现在是冗长的迂腐解释,有太多的离题:


argv是一个指针,特别是指向指针的指针char.作为参数声明(在该上下文中),char *argv[]相当于char **argv.

sizeof (argv)char**指针中的字节数.

sizeof (argv[0])char*指针中的字节数.

sizeof (argv) / sizeof (argv[0])很可能是1(假设char*char**具有相同的大小,这是他们在大多数的实现做).

现在对于被定义为数组对象的东西:

some_type an_array[COUNT];
Run Code Online (Sandbox Code Playgroud)

表达确实有效; 这个:

sizeof an_array / sizeof an_array[0]
Run Code Online (Sandbox Code Playgroud)

确实给你了元素的数量an_array,即COUNT.我认为,原因应该是相当明显的.数组中的字节数是数组的一个元素中的字节数乘以元素数.所以:

sizeof an_array == sizeof an_array[0] * COUNT
Run Code Online (Sandbox Code Playgroud)

并重新安排条款:

sizeof an_array / sizeof an_array[0] == COUNT
Run Code Online (Sandbox Code Playgroud)

顺便提一下,由于索引操作符在C中定义的方式,sizeof an_array[0]也可以写成sizeof *an_array.

(注意sizeof,如果该参数是一个表达式,例如对象名,则运算符不需要括号括起来.操作数sizeof是表达式或带括号的类型名称.但如果您更喜欢始终使用括号sizeof,则可以那样做.)

这是计算数组中元素数量的常用习惯用法 - 但只有当您拥有数组本身的名称而不是指向其第一个元素的指针时,它才有效.

[以下适用于C.我相信它也适用于C++(我最初没有注意到问题标记为C++,而不是C).]

在回答评论中提出的问题时,不,char*并且char**不需要具有相同的大小.C标准对指针表示的要求是:

指向void的指针应具有与指向字符类型的指针相同的表示和对齐要求.同样,指向兼容类型的限定或非限定版本的指针应具有相同的表示和对齐要求.所有指向结构类型的指针都应具有相同的表示和对齐要求.所有指向union类型的指针都应具有相同的表示和对齐要求.指向其他类型的指针不需要具有相同的表示或对齐要求.

参考:N1570,6.2.5p28.

C++标准至少有一部分内容; N3485草案第3.9.2节[basic.compound]说:

类型的对象CV void*应具有相同的表示和对准要求CV char*.

我没有找到我从C标准中引用的其余部分的相应文本.

在字寻址机器上,char*指针可能需要更多信息来指定该字内的字和字节,而不是char**指针所需的字,只需要指定一个对齐的字.