猿问

函数参数中的数组长度

函数参数中的数组长度

这是以C语言计算数组长度的著名代码:

sizeof(array)/sizeof(type)

但是,我似乎找不出作为参数传递给函数的数组的长度:

#include <stdio.h>int length(const char* array[]) {
  return sizeof(array)/sizeof(char*);}int main() {
  const char* friends[] = { "John", "Jack", "Jim" };
  printf("%d %d", sizeof(friends)/sizeof(char*), length(friends)); // 3 1}

我假设数组是作为常量指针按值复制到函数参数的,对它的引用应该可以解决这个问题,但是这个声明是无效的:

int length(const char**& array);

我发现将数组长度作为第二个参数传递为冗余信息,但是为什么标准声明是main就像这样:

int main(int argc, char** argv);

请解释是否可以在函数参数中找到数组长度,如果可以,为什么在main.


MMMHUHU
浏览 601回答 3
3回答

杨魅力

sizeof只有在将数组应用于原始数组时,才能找到数组的长度。int&nbsp;a[5];&nbsp;//real&nbsp;array.&nbsp;NOT&nbsp;a&nbsp;pointersizeof(a);&nbsp;//&nbsp;:)但是,当数组衰变为指针时,大小将给出指针的大小,而不是数组的大小。int&nbsp;a[5];int&nbsp;*&nbsp;p&nbsp;=&nbsp;a;sizeof(p);&nbsp;//&nbsp;:(正如您已经很清楚地指出的那样,main作为参数接收数组的长度(ARGC)。是的,这是出于必要,不是多余的。..(嗯,它有点红,因为argv被一个空指针很方便地结束了,但是我偏离了)。对于为什么会发生这种情况,有一些理由。我们怎样才能使一个C数组也知道它的长度呢?第一个想法是不要让数组在传递给函数时衰减到指针中,并且在类型系统中继续保持数组长度。这样做的不好之处在于,您需要为每个可能的数组长度设置一个单独的函数,这样做并不是一个好主意。(帕斯卡做了这件事,有些人认为这是它“输给”C的原因之一)第二个想法是将数组长度存储在数组旁边,就像现代编程语言所做的那样:a&nbsp;->&nbsp;[5];[0,0,0,0,0]但是你只是在创造一个无形的struct幕后和C哲学不赞成这种开销。尽管如此,自己创建这样一个结构通常是解决某些问题的一个好主意:struct&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;size_t&nbsp;length; &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;*&nbsp;elements;}您可以考虑的另一件事是,C中的字符串是如何终止的,而不是存储长度(就像Pascal中的那样)。要存储长度而不必担心限制,需要一个扑通四个字节,这是一个难以想象的代价(至少在当时)。人们可能想知道数组是否也可以像那样以空结尾,但是如何允许数组存储空值呢?

素胚勾勒不出你

阵列腐朽传递到指针。“常见问题”第6.4节很好地涵盖了这一点,并提供了K&R参考资料等。另外,假设函数可以知道指针中分配的内存的大小。您可以调用该函数两次或更多次,每次都使用不同的输入数组,它们的长度可能不同;因此,长度必须作为一个秘密隐藏变量传入。然后考虑是否将偏移量传递给另一个数组,或者在堆上分配的数组(malloc所有这些都是库函数-编译器链接到的东西,而不是它的主体和原因)。很难想象,如果没有一些幕后的切片对象,这是如何工作的,对吧?塞班AllocSize()函数返回分配的大小。malloc()这只适用于malloc返回的文字指针,如果您要求malloc知道无效指针或指针偏移量的大小,就会出现gobbledygook或崩溃。你不想相信这是不可能的,但事实并非如此。了解传递给函数的东西的长度的唯一方法是自己跟踪长度,并将其作为单独的显式参数传递给自己。

千万里不及你

正如@Will所述,衰变发生在参数传递过程中。绕过它的一种方法是传递元素的数量。若要添加到此,您可能会发现_countof()宏有用-它所做的与您所做的相当;)
随时随地看视频慕课网APP
我要回答