这是用C计算数组长度的众所周知的代码:
sizeof(array)/sizeof(type)
Run Code Online (Sandbox Code Playgroud)
但我似乎无法找出作为函数参数传递的数组的长度:
#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
}
Run Code Online (Sandbox Code Playgroud)
我假设数组通过值复制到函数参数作为常量指针,并且对它的引用应解决此问题,但此声明无效:
int length(const char**& array);
Run Code Online (Sandbox Code Playgroud)
我发现将数组长度作为第二个参数传递为冗余信息,但为什么标准声明main如下:
int main(int argc, char** argv);
Run Code Online (Sandbox Code Playgroud)
请解释是否可以在函数参数中找出数组长度,如果是,那么为什么存在冗余main.
hug*_*omg 61
sizeof 只有在将数组应用于原始数组时才能找到数组的长度.
int a[5]; //real array. NOT a pointer
sizeof(a); // :)
Run Code Online (Sandbox Code Playgroud)
但是,当数组衰减成指针时,sizeof将给出指针的大小而不是数组的大小.
int a[5];
int * p = a;
sizeof(p); // :(
Run Code Online (Sandbox Code Playgroud)
正如你已经巧妙地指出main接收数组的长度作为参数(argc).是的,这是不必要的,并不是多余的.(好吧,它是一种还原剂,因为argv很方便地被一个空指针终止但我离题了)
有一些理由说明为什么会这样.我们怎样才能让C数组知道它的长度呢?
第一个想法是,当数组传递给函数并继续将数组长度保持在类型系统中时,数组不会衰减为指针.关于这一点的坏处是你需要为每个可能的数组长度都有一个单独的函数,这样做并不是一个好主意.(Pascal做到了这一点,有些人认为这是它"失去"C的原因之一)
第二个想法是将数组长度存储在数组旁边,就像任何现代编程语言一样:
a -> [5];[0,0,0,0,0]
Run Code Online (Sandbox Code Playgroud)
但是,你只是struct在幕后创造一个看不见的东西,C哲学并不赞成这种开销.也就是说,自己创建这样的结构对于某些问题通常是一个好主意:
struct {
size_t length;
int * elements;
}
Run Code Online (Sandbox Code Playgroud)
您可以考虑的另一件事是C中的字符串如何以空终止而不是存储长度(如在Pascal中).存储长度而不用担心限制需要高达四个字节,这是一个难以想象的昂贵数量(至少在当时).有人可能想知道数组是否也可以像这样终止null,但是如何允许数组存储空?
Wil*_*ill 12
传递时,数组衰减为指针.
C FAQ的第6.4节非常清楚地介绍了这一点并提供了K&R参考文献等.
除此之外,假设函数可以知道指针中分配的内存大小.您可以调用该函数两次或更多次,每次使用可能不同长度的不同输入数组; 因此,长度必须以某种方式作为秘密隐藏变量传递.然后考虑是否将偏移量传入另一个数组,或者在堆上分配的数组(malloc以及所有库函数 - 编译器链接到的内容,而不是查看和查看主体的原因).
很难想象如果没有一些幕后切片对象,这可能会如何工作呢?
Symbian确实有一个AllocSize()返回分配大小的函数malloc(); 这只适用于malloc返回的文字指针,如果你要求它知道无效指针的大小或偏离指针的指针,你就会得到gobbledygook或者崩溃.
你不想相信它不可能,但它真的不是.知道传递给函数的内容长度的唯一方法是自己跟踪长度并将其作为单独的显式参数传递给自己.