数组的大小…在C / C ++中?
好的,所以你有和数组A [] …在某些函数中传递给你,比如使用以下函数原型:
void foo(int A[]);
好的,正如你所知,在不知道某种结束变量或已知大小的情况下很难找到该数组的大小……
那么这里是交易。 我似乎有些人在挑战问题上弄明白了,我不明白他们是如何做到的。 我当然无法看到他们的源代码,这就是我在这里问的原因。
有谁知道甚至可以远程查找该数组的大小? 也许就像free()函数在C中做的那样?
你觉得这怎么样??
template int ArrLength(E(&)[size]){return size;} void main() { int arr[17]; int sizeofArray = ArrLength(arr); }
该函数的签名不是采用数组的函数的签名,而是指向 int
的指针 。 您无法在函数中获取数组的大小,并且必须将其作为函数的额外参数传递。
如果允许更改函数的签名,则有不同的替代方法:
C / C ++(简单):
void f( int *data, int size ); // function f( array, sizeof array/sizeof array[0] ); // caller code
C ++:
template void f( int (&array)[N] ); // Inside f, size N embedded in type f( array ); // caller code
C ++(虽然是一个调度):
template void f( int (&array)[N] ) { // Dispatcher f( array, N ); } void f( int *array, int size ); // Actual function, as per option 1 f( array ); // Compiler processes the type as per 2
你不能这样做。 您可以使用约定来表示数组的结尾(例如,它由非零整数后跟0组成),或者您传输数组的大小(通常作为附加参数)。
如果你使用Boehm垃圾收集器 (它有很多好处,特别是你用GC_malloc
和朋友分配,但你不关心显式free
内存),你可以使用GC_size
函数来给你一个大小的GC_malloc
-ed内存区域,但标准malloc
没有此function。
您问的是我们对以下代码的看法:
template int ArrLength(E(&)[size]){return size;} void main() { int arr[17]; int sizeofArray = ArrLength(arr); }
好吧, void main
从未成为标准,无论是在C还是在C ++中。
这是int main
。
关于ArrLength
函数,正确的实现不适用于C ++ 98中的本地类型。 它适用于C ++ 11规则的本地类型。 但是在C ++ 11中你可以写出end(a) - begin(a)
。
您显示的实现不正确:它绝对不应该有int
模板参数。 把它变成ptrdiff_t
。 例如,在64位Windows中, int
类型仍为32位。
最后,作为一般建议:
- 使用
std::vector
和std::array
。
这种方法的一个相关好处是它避免丢弃大小信息,即它避免产生你所问的问题。 还有许多其他优点。 所以,试试吧。
干杯和hth。
第一个元素可以是计数,或者最后一个元素可以是哨兵。 这就是我能想到的所有可以移植的东西。
在新代码中,对于容器不可知的代码,更喜欢传递两个迭代器(或C中的指针)作为比传递原始数组更好的解决方案。 对于特定于容器的代码,请使用像vector
这样的C ++容器。
不,你不能。 你的原型相当于
void foo(int * A);
显然没有尺寸信息。 依赖于实现的技巧也无济于事:
- 数组变量可以在堆栈上分配或者是静态的,因此
malloc
或朋友没有提供任何信息 - 如果在堆上分配,则不强制该函数的用户使用分配的第一个元素调用它。
例如以下是有效的
int B[22]; foo(B); int * A = new int[33]; foo(A + 25);
这是我不建议做的事情,但是如果你知道数组开头的地址和定义的下一个变量/结构的地址,你可以减去地址。 可能不是一个好主意。
可能在编译时分配的数组在可执行文件的调试信息中有关于其大小的信息。 此外,可以在代码中搜索与编译时分配的变量相对应的所有地址,并假设数组的大小减去其起始地址与任何变量的下一个最接近的起始地址之间的差值。
对于dinamically分配的变量,应该可以从堆数据结构中获取其大小。
它是hacky和系统依赖,但它仍然是一个可能的解决方案。
一个估计如下:如果你有一个int
数组,但知道它们介于(愚蠢的例子) 0..80000
,那么第一个数字元素是负数或大于80000
可能正好超过结束arrays。
这有时可以工作,因为直到数组末尾的内存(我假设它是动态分配的)将不会被程序初始化(因此可能包含垃圾值),但可能仍然是分配的一部分页面,取决于数组的大小。 在其他情况下,它将崩溃或无法提供有意义的输出。
所有其他答案可能都更好,即您必须传递数组的长度或使用特殊的字节序列终止它。
以下方法不可移植,但它在VS2005中适用于我:
int getSizeOfArray( int* ptr ) { int size = 0; void* ptrToStruct = ptr; long adr = (long)ptrToStruct; adr = adr - 0x10; void* ptrToSize = (void*)adr; size = *(int*)ptrToSize; size /= sizeof(int); return size; }
这完全取决于编译器和系统的内存模型,因此它也不可移植。 我敢打赌,其他平台有相同的方法。 我绝不会在生产环境中使用它,只是说明这是另一种选择。
你可以使用这个: int n = sizeof(A) / sizeof(A[0]);