我有一个int
数组,我需要找到它中的元素数量。我知道这与sizeof
有关,但我不确定如何使用它。
如果你的数组在范围内,你可以使用sizeof
来确定它的大小(以字节为单位)并使用除法来计算元素的数量:
#define NUM_OF_ELEMS 10
int arr[NUM_OF_ELEMS];
size_t NumberOfElements = sizeof(arr)/sizeof(arr[0]);
如果您将数组作为函数参数接收或在堆中分配数组,则无法使用sizeof
确定其大小。你必须以某种方式存储/传递大小信息才能使用它:
void DoSomethingWithArray(int* arr, int NumOfElems)
{
for(int i = 0; i < NumOfElems; ++i) {
arr[i] = /*...*/
}
}
超级容易。
只需使用sizeof()
将分配的字节数除以数组数据类型的字节数。
例如。给定一个名为myArray
的整数数组
int numArrElements = sizeof(myArray) / sizeof(int);
现在,如果数组的数据类型不是常数并且可能会更改,则使等式中的除数使用第一个值的大小作为数据类型的大小
EG
int numArrElements = sizeof(myArray) / sizeof(myArray[0]);
我大多发现一种简单的方法来执行循环内部的数组长度
int array[] = {10, 20, 30, 40};
int i;
for (i = 0; i < array[i]; i++) {
printf("%d\n", array[i]);
}
实际上,没有适当的方法来计算动态整数数组中的元素。但是,sizeof命令在Linux中正常工作,但在Windows中无法正常工作。从程序员的角度来看,不建议使用sizeof来获取动态数组中的元素数量。我们应该在制作数组时跟踪元素的数量。
int a[20];
int length;
length = sizeof(a) / sizeof(int);
并且您可以使用其他方法使您的代码不被硬编码为int
假如你有一个数组array
你只需要:
int len = sizeof(array) / sizeof(array[0]);
我个人认为sizeof(a)/ sizeof(* a)看起来更干净。
我也更喜欢将它定义为宏:
#define NUM(a) (sizeof(a) / sizeof(*a))
然后你可以在for循环中使用它,因此:
for (i = 0; i < NUM(a); i++)
除非是字符数组,否则无法找到数组中的元素数。考虑以下示例:
int main()
{
int arr[100]={1,2,3,4,5};
int size = sizeof(arr)/sizeof(arr[0]);
printf("%d", &size);
return 1;
}
即使元素数为5,上面的值也给出了值100。如果它是一个字符数组,您可以线性搜索数组末尾的空字符串,并在您通过时增加计数器。
我使用上面建议的以下代码来评估我的二维数组中的元素数量:
#include <stdio.h>
#include <string.h>
void main(void)
{
char strs[3][20] =
{
{"January"},
{"February"},
{""}
};
int arraysize = sizeof(strs)/sizeof(strs[0]);
for (int i = 0; i < arraysize; i++)
{
printf("Month %d is: %s\n", i, strs[i]);
}
}
它工作得很好。据我所知,你不能在C数组中混淆不同的数据类型,并且你应该拥有所有数组元素的相同大小(如果我是对的),因此你可以利用这个小技巧来利用它:
对于C中的2d数组,此剪切应该是可移植的,但是在其他编程语言中,它无法工作,因为您可以在不同大小的数组中使用不同的数据类型(如JAVA中)。
#include<stdio.h>
int main()
{
int arr[]={10,20,30,40,50,60};
int *p;
int count=0;
for(p=arr;p<&arr+1;p++)
count++;
printf("The no of elements in array=%d",count);
return 0;
}
OUTPUT = 6
说明
p
是指向一维数组的指针,在循环for(p=arr,p<&arr+1;p++)
中,我使p
指向基址。假设它的基地址是1000;如果我们增加p
然后它指向1002,依此类推。现在来看&arr
的概念 - 它基本上代表整个数组,如果我们在整个数组中加1,即&arr+1
,它给出地址1012,即下一个1-D数组的地址(在我们的例子中,int的大小是2),因此条件变为1000 <1012。
所以,基本上情况变成了
for(p=1000;p<1012;p++)
现在让我们检查条件并计算值
p=1000
和p<1012
条件是true
:进入循环,将count
的值增加到1。p=1002
和p<1012
条件是true
:进入循环,将count
的值增加到2。p=1010
和p<1012
条件是true
:进入循环,将count
的值增加到6。p=1012
和p<1012
条件为假:在count=6
声明中打印printf
的值。如果我们不知道数组中元素的数量以及用户在运行时何时给出输入。然后我们可以编写代码
C代码:
while(scanf("%d",&array[count])==1) {
count++;
}
C ++代码:
while(cin>>a[count]) {
count++;
}
现在,计数将具有输入的数组元素的数量。
问题很简单:给定一个C ++数组(例如x
中的int x[10]
),你将如何获得其中的元素数量?
一个明显的解决方案是以下宏(定义1):
#define countof( array ) ( sizeof( array )/sizeof( array[0] ) )
我不能说这是不正确的,因为当你给它一个数组它确实给出了正确的答案。但是,当您提供不是数组的东西时,相同的表达式会让您感到虚假。例如,如果你有
int * p;
然后countof( p )
总是在一台机器上给你1,其中int指针和int具有相同的大小(例如在Win32平台上)。
此宏还错误地接受具有成员函数operator []的类的任何对象。例如,假设你写
class IntArray {
private:
int * p;
size_t size;
public:
int & operator [] ( size_t i );
} x;
那么sizeof( x )
将是x对象的大小,而不是x.p
指向的缓冲区的大小。因此,你不会得到countof( x )
的正确答案。
因此我们得出结论,定义1并不好,因为编译器不会阻止您滥用它。它无法强制只传入一个数组。
什么是更好的选择?
好吧,如果我们希望编译器确保countof的参数始终是一个数组,我们必须找到一个只允许数组的上下文。相同的上下文应该拒绝任何非数组表达式。
一些初学者可能会尝试这个(定义2):
template <typename T, size_t N>
size_t countof( T array[N] )
{
return N;
}
他们认为,这个模板函数将接受N个元素的数组并返回N.
不幸的是,这不能编译,因为C ++将数组参数视为与指针参数相同,即上面的定义相当于:
template <typename T, size_t N>
size_t countof( T * array )
{
return N;
}
现在很明显,函数体无法知道N是什么。
但是,如果函数需要数组引用,则编译器会确保实际参数的大小与声明匹配。这意味着我们可以通过一个小修改使定义2工作(定义3):
template <typename T, size_t N>
size_t countof( T (&array)[N] )
{
return N;
}
这个计数非常有效,你不能通过给它一个指针来欺骗它。但是,它是一个功能,而不是宏。这意味着您不能在需要编译时常量的地方使用它。特别是,你不能写像:
int x[10];
int y[ 2*countof(x) ]; // twice as big as x
我们可以做些什么吗?
有人(我不知道它是谁 - 我只是在一段来自未知作者的代码中看到它)提出了一个聪明的想法:将N从函数体转移到返回类型(例如使函数返回一个N元素的数组),然后我们可以获得N的值而不实际调用该函数。
确切地说,我们必须使函数返回一个数组引用,因为C ++不允许您直接返回数组。
这个的实现是:
template <typename T, size_t N>
char ( &_ArraySizeHelper( T (&array)[N] ))[N];
#define countof( array ) (sizeof( _ArraySizeHelper( array ) ))
不可否认,语法看起来很糟糕。实际上,一些解释是必要的。
首先,顶级的东西
char ( &_ArraySizeHelper( ... ))[N];
_ArraySizeHelper
是一个函数,它返回一个引用(注意&)到N个元素的char数组。
接下来,函数参数是
T (&array)[N]
这是对N个元素的T数组的引用。
最后,countof
被定义为函数_ArraySizeHelper
的结果的大小。注意我们甚至不需要定义_ArraySizeHelper()
, - 声明就足够了。
有了这个新定义,
int x[10];
int y[ 2*countof(x) ]; // twice as big as x
变得有效,就像我们想要的那样。
我现在开心吗?好吧,我认为这个定义肯定比我们访问过的其他定义更好,但它仍然不是我想要的。首先,它不适用于函数内定义的类型。这是因为模板函数_ArraySizeHelper
需要一个可在全局范围内访问的类型。
我没有更好的解决方案。如果您知道,请告诉我。
sizeof
返回它的参数的字节大小。这不是你想要的,但它可以帮助你。
假设你有一个数组:
int array[4];
如果将sizeof
应用于数组(sizeof(array)
),它将返回其大小(以字节为单位),在这种情况下,它的大小为int
的4 *,因此总共可能为16个字节(取决于您的实现)。
如果将sizeof
应用于数组的元素(sizeof(array[0])
),它将返回其大小(以字节为单位),在本例中为int
的大小,因此总共可能有4个字节(取决于您的实现)。
如果你将第一个除以第二个,它将是:(4 * int
的大小)/(int
的大小)= 4;这正是你想要的。
所以这应该做:
sizeof(array) / sizeof(array[0])
现在您可能希望有一个宏来封装这个逻辑,而不必再考虑应该如何完成它:
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
您需要括起所有宏的括号,就像在任何其他复杂的宏中一样,并且还包含每个变量,以避免与运算符优先级相关的意外错误。
现在你可以在任何这样的数组上使用它:
int array[6];
ptrdiff_t nmemb;
nmemb = ARRAY_SIZE(array);
/* nmemb == 6 */
请记住,声明为数组的函数的参数不是真正的数组,而是指向数组的第一个元素的指针,因此这对它们不起作用:
void foo(int false_array[6])
{
ptrdiff_t nmemb;
nmemb = ARRAY_SIZE(false_array);
/* nmemb == sizeof(int *) / sizeof(int) */
/* (maybe ==2) */
}
但是如果将指针传递给数组而不仅仅是数组,它可以在函数中使用:
void bar(int (*arrptr)[7])
{
ptrdiff_t nmemb;
nmemb = ARRAY_SIZE(*arrptr);
/* nmemb == 7 */
}