c - 函数参数中的数组长度

标签 c pointers

这是在 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中会有冗余。


最佳答案

sizeof 仅在将其应用于原始数组时才能计算出数组的长度。

int a[5]; //real array. NOT a pointer
sizeof(a); // :)

但是,当数组衰减为指针时,sizeof 将给出指针的大小而不是数组的大小。

int a[5];
int * p = a;
sizeof(p); // :(

正如您已经聪明地指出的那样,main 接收数组的长度作为参数 (argc)。 是的,这是出于必要而不是多余的。 (好吧,这有点多余,因为 argv 很方便地被空指针终止,但我离题了)

关于为什么会发生这种情况,有一些推理。我们怎样做才能让 C 数组也知道它的长度?

第一个想法是在将数组传递给函数时不要让数组退化为指针,并继续在类型系统中保持数组长度。这样做的坏处是您需要为每个可能的数组长度设置一个单独的函数,而这样做并不是一个好主意。 (Pascal 做到了这一点,有人认为这是它“输给”C 的原因之一)

第二个想法是将数组长度存储在数组旁边,就像任何现代编程语言所做的那样:

a -> [5];[0,0,0,0,0]

但是你只是在幕后创建了一个不可见的 struct 并且 C 哲学不赞成这种开销。也就是说,自己创建这样的结构通常是解决某些问题的好主意:

struct {
    size_t length;
    int * elements;
}

您可以考虑的另一件事是 C 中的字符串如何以 null 终止而不是存储长度(如在 Pascal 中)。要存储长度而不用担心限制,需要 高达 四个字节,这是一个难以想象的昂贵数量(至少在当时是这样)。人们可能想知道数组是否也可以像那样以 null 终止,但是您将如何允许数组存储 null?

关于c - 函数参数中的数组长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8269048/

相关文章:

c++ - 这个链表遍历有什么问题?

c - 标量集成

仅当我在 glEnd 之后调用 glPopMatrix 时才会显示立方体(而不是相反)

c - 重复字母的代码如何工作?

c - 在结构体中使用指向结构体数组的指针

c++ - 为什么将 "pointer to pointer to non-const"转换为 "pointer to pointer to const"是不合法的

c - 通过指针访问结构中的指针

c - 为什么每次循环我的 sum 和 count 值都会丢失?

C: pipe() 和 fork()

pointers - 范围引用而不是值