如果数组传递给另一个函数(未传递大小),是否可以确定数组的大小?该数组初始化为int array [] = {XXX} ..
我知道不可能做sizeof,因为它会返回指针的大小。我问的原因是因为我需要在传递数组的其他函数内运行for循环。我试过像:
for( int i = 0; array[i] != NULL; i++) {
........
}
但是我注意到在数组的近端,array [i]有时包含像758433这样的垃圾值,这不是数组初始化中指定的值。
答案 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为基础,这是一个更大的示例,展示了以下原理:
使用对给定大小的数组的引用来强制给定函数参数输入数组的大小,如下所示:
void foo2(uint8_t (&array)[100])
{
printf("sizeof(array) = %lu\n", sizeof(array));
}
和:
通过使用函数 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){
...
}