如果传递给函数,则确定数组的大小

时间:2009-06-09 03:28:47

标签: c++ arrays null pointers

如果数组传递给另一个函数(未传递大小),是否可以确定数组的大小?该数组初始化为int array [] = {XXX} ..

我知道不可能做sizeof,因为它会返回指针的大小。我问的原因是因为我需要在传递数组的其他函数内运行for循环。我试过像:

for( int i = 0; array[i] != NULL; i++) {
........
}

但是我注意到在数组的近端,array [i]有时包含像758433这样的垃圾值,这不是数组初始化中指定的值。

10 个答案:

答案 0 :(得分:47)

其他答案忽略了c ++的一个特征。您可以通过引用传递数组,并使用模板:

template <typename T, int N>
void func(T (&a) [N]) {
    for (int i = 0; i < N; ++i) a[i] = T(); // reset all elements
}

然后你可以这样做:

int x[10];
func(x);

但请注意,这仅适用于数组,而不适用于指针。

但是,正如其他答案所指出的那样,使用std::vector是更好的选择。

答案 1 :(得分:13)

如果它在您的控制范围内,请使用STL容器,例如vector或deque而不是数组。

答案 2 :(得分:9)

不,这是不可能的。

一种解决方法:在数组的最后一个值处放置一个特殊值,以便您可以识别它。

答案 3 :(得分:6)

一个明显的解决方案是使用STL。如果不可能,最好明确传递数组长度。 对于这种特殊情况,我对使用哨兵值技巧持怀疑态度。有用     更好的指针数组,因为NULL是一个很好的哨兵值。同     整数数组,它并不那么容易 - 你需要拥有     一个“神奇的”哨兵值,即     不好。

旁注:如果您的数组已定义并初始化为

 int array[] = { X, Y, Z };

与你的循环在同一范围内,然后

sizeof(array)将以字节为单位返回实际大小,而不是指针的大小。您可以将数组长度设为

sizeof(array) / sizeof(array[0])

但是,在一般情况下,如果将数组作为指针,则不能使用此技巧。

答案 4 :(得分:4)

您可以在int数组中添加终结符,然后手动逐步遍历数组以发现方法中的大小。

#include<iostream>
using namespace std;

int howBigIsBareArray(int arr[]){
    int counter = 0;
    while (arr[counter] != NULL){
        counter++;
    }
    return counter;
}
int main(){
    int a1[6] = {1,2,3,4,5,'\0'};
    cout << "SizeOfMyArray: " << howBigIsBareArray(a1);
}

此程序打印:

SizeOfMyArray: 5

这是O(n)时间复杂度操作,这是不好的。你永远不应该只是为了发现它的大小来踩过数组。

答案 5 :(得分:3)

如果你无法传递大小,你最后需要一个可区分的 sentinel 值(你需要自己把它放在那里 - 正如你所发现的那样,你不能信任C ++为您自动完成!)。没有办法让被调用的函数神奇地调整大小,如果没有传入,并且没有使用明确,可靠的哨兵。

答案 6 :(得分:1)

您可以尝试将空字符\0附加到数组然后发送吗?这样,您可以在循环中检查\ 0。

答案 7 :(得分:0)

实际上Chucks列出了

for(int i = 0; array [i]!= NULL; i ++){ ........ }

每次通话前的尺寸都是浪费的,需要知道你得到了什么。

如果在数组的末尾添加NULL,则效果很好。

为什么?对于嵌入式设计,在每个例程中传递sizeof使得每个调用与每个数组的NULL相比非常大。我有一个2K的PIC16F684芯片,它使用传输的sizeof和阵列进行12次调用,占用芯片的10%。只有阵列和Chucks代码与NULLS om每个阵列...我需要4%。

一个真实的例子..感谢chuck好的电话。

答案 8 :(得分:0)

我本来是为了回答另一个问题:When a function has a specific-size array parameter, why is it replaced with a pointer?,但由于将它直接回答了这个问题,所以将其移到这里。


@Richard Corden's answer@sbi's answer为基础,这是一个更大的示例,展示了以下原理:

  1. 使用对给定大小的数组的引用来强制给定函数参数输入数组的大小,如下所示:

     void foo2(uint8_t (&array)[100]) 
     {
         printf("sizeof(array) = %lu\n", sizeof(array)); 
     }
    

    和:

  2. 通过使用函数 template 并引用给定模板参数大小为{{的输入数组,允许使用 any 大小的函数参数输入数组。 1}},就像这样:

    N

看下面的完整示例:

请注意,此函数原型完全不知道数组大小 ! (这里的 template<size_t N> void foo3(uint8_t (&array)[N]) { printf("sizeof(array) = %lu\n", sizeof(array)); } 只是对用户的视觉提示/提醒,但对编译器毫无影响或影响!):

100

...此函数原型仅允许固定大小为100的输入数组:

void foo(uint8_t array[100]) {}

...并且此函数 template 原型允许输入任意大小的数组,并在编译时静态知道其大小(这就是模板的工作方式):

void foo2(uint8_t (&array)[100]) {}

以下是完整示例:

您可以在这里自己运行:https://onlinegdb.com/rkyL_tcBv

template<size_t N>
void foo3(uint8_t (&array)[N]) {}

示例输出:

(编译器警告,指的是#include <cstdint> #include <cstdio> void foo(uint8_t array[100]) { // is ALWAYS sizeof(uint8_t*), which is 8! printf("sizeof(array) = %lu\n", sizeof(array)); } void foo2(uint8_t (&array)[100]) { printf("sizeof(array) = %lu\n", sizeof(array)); } template<size_t N> void foo3(uint8_t (&array)[N]) { printf("sizeof(array) = %lu\n", sizeof(array)); } int main() { printf("Hello World\n"); printf("\n"); uint8_t a1[10]; uint8_t a2[11]; uint8_t a3[12]; // Is `sizeof(array) = 8` for all of these! foo(a1); foo(a2); foo(a3); printf("\n"); // Fails to compile for these 3! Sample error: // > main.cpp:49:12: error: invalid initialization of reference of type ‘uint8_t (&)[100] // > {aka unsigned char (&)[100]}’ from expression of type ‘uint8_t [10] {aka unsigned char [10]}’ // > foo2(a1); // > ^ // foo2(a1); // foo2(a2); // foo2(a3); // ------------------ // Works just fine for this one since the array `a4` has the right length! // Is `sizeof(array) = 100` uint8_t a4[100]; foo2(a4); printf("\n"); foo3(a1); foo3(a2); foo3(a3); foo3(a4); printf("\n"); return 0; } 中的sizeof调用):

foo()

(标准输出“标准输出”):

main.cpp:26:49: warning: ‘sizeof’ on array function parameter ‘array’ will return size of ‘uint8_t* {aka unsigned char*}’ [-Wsizeof-array-argument]                               
main.cpp:23:27: note: declared here                                                                                                                                               

答案 9 :(得分:0)

这不应该吗?至少对于 Arduino(AVR) c++ 之类的东西。

//rename func foo to foo_ then
#define foo(A) foo_(A, sizeof(A))

void foo_(char a[],int array_size){
...
}