如何确定C语言中数组的大小?

也就是说,数组可以容纳多少个元素?


#1楼

如果您要处理未作为参数接收的数组,则sizeof方法是正确的方法。 作为参数发送给函数的数组被视为指针,因此sizeof将返回指针的大小,而不是数组的大小。

因此,内部函数无法使用此方法。 相反,请始终传递一个附加参数size_t size指示数组中元素的数量。

测试:

#include <stdio.h>
#include <stdlib.h>void printSizeOf(int intArray[]);
void printLength(int intArray[]);int main(int argc, char* argv[])
{int array[] = { 0, 1, 2, 3, 4, 5, 6 };printf("sizeof of array: %d\n", (int) sizeof(array));printSizeOf(array);printf("Length of array: %d\n", (int)( sizeof(array) / sizeof(array[0]) ));printLength(array);
}void printSizeOf(int intArray[])
{printf("sizeof of parameter: %d\n", (int) sizeof(intArray));
}void printLength(int intArray[])
{printf("Length of parameter: %d\n", (int)( sizeof(intArray) / sizeof(intArray[0]) ));
}

输出(在64位Linux操作系统中):

sizeof of array: 28
sizeof of parameter: 8
Length of array: 7
Length of parameter: 2

输出(在32位Windows操作系统中):

sizeof of array: 28
sizeof of parameter: 4
Length of array: 7
Length of parameter: 1

#2楼

您可以使用&运算符。 这是源代码:

#include<stdio.h>
#include<stdlib.h>
int main(){int a[10];int *p; printf("%p\n", (void *)a); printf("%p\n", (void *)(&a+1));printf("---- diff----\n");printf("%zu\n", sizeof(a[0]));printf("The size of array a is %zu\n", ((char *)(&a+1)-(char *)a)/(sizeof(a[0])));return 0;
};

这是示例输出

1549216672
1549216712
---- diff----
4
The size of array a is 10

#3楼

如果您真的想通过数组来传递数据,那么我建议您实现一个结构,以存储指向您想要的数组类型的指针和一个表示数组大小的整数。 然后,您可以将其传递给函数。 只需将数组变量值(指向第一个元素的指针)分配给该指针。 然后,您可以转到Array.arr[i]以获取第i个元素,并使用Array.size来获取数组中的元素数。

我为您提供了一些代码。 它不是很有用,但您可以使用更多功能进行扩展。 不过,老实说,如果您要这些,就应该停止使用C,并使用内置这些功能的另一种语言。

/* Absolutely no one should use this...By the time you're done implementing it you'll wish you just passed aroundan array and size to your functions */
/* This is a static implementation. You can get a dynamic implementation and cut out the array in main by using the stdlib memory allocation methods,but it will work much slower since it will store your array on the heap */#include <stdio.h>
#include <string.h>
/*
#include "MyTypeArray.h"
*/
/* MyTypeArray.h
#ifndef MYTYPE_ARRAY
#define MYTYPE_ARRAY
*/
typedef struct MyType
{int age;char name[20];
} MyType;
typedef struct MyTypeArray
{int size;MyType *arr;
} MyTypeArray;MyType new_MyType(int age, char *name);
MyTypeArray newMyTypeArray(int size, MyType *first);
/*
#endif
End MyTypeArray.h *//* MyTypeArray.c */
MyType new_MyType(int age, char *name)
{MyType d;d.age = age;strcpy(d.name, name);return d;
}MyTypeArray new_MyTypeArray(int size, MyType *first)
{MyTypeArray d;d.size = size;d.arr = first;return d;
}
/* End MyTypeArray.c */void print_MyType_names(MyTypeArray d)
{int i;for (i = 0; i < d.size; i++){printf("Name: %s, Age: %d\n", d.arr[i].name, d.arr[i].age);}
}int main()
{/* First create an array on the stack to store our elements in.Note we could create an empty array with a size instead andset the elements later. */MyType arr[] = {new_MyType(10, "Sam"), new_MyType(3, "Baxter")};/* Now create a "MyTypeArray" which will use the array we justcreated internally. Really it will just store the value of the pointer"arr". Here we are manually setting the size. You can use the sizeoftrick here instead if you're sure it will work with your compiler. */MyTypeArray array = new_MyTypeArray(2, arr);/* MyTypeArray array = new_MyTypeArray(sizeof(arr)/sizeof(arr[0]), arr); */print_MyType_names(array);return 0;
}

#4楼

sizeof技巧是我所知道的最好方法,在括号的使用上有一个很小但(对我来说,这是一个主要的挑战)。

维基百科条目清楚地表明,C的sizeof不是函数。 它是一个运算符 。 因此,除非参数是类型名称,否则不需要在参数周围加上括号。 这很容易记住,因为它使参数看起来像强制转换表达式,该表达式也使用括号。

因此:如果您具有以下条件:

int myArray[10];

您可以使用以下代码找到元素数量:

size_t n = sizeof myArray / sizeof *myArray;

对我来说,这比带括号的替代方法容易读得多。 我也赞成在该部门的右侧使用星号,因为它比索引更简洁。

当然,这也都是编译时,因此无需担心划分会影响程序的性能。 因此,请尽可能使用此表格。

最好是在有一个实际对象时在一个对象上使用sizeof,而不是在一个类型上,因为这样一来,您就不必担心会出错并指出错误的类型。

例如,假设您有一个函数,例如通过网络将某些数据作为字节流输出。 让我们调用函数send() ,并使其以指向要发送的对象的指针以及对象中的字节数作为参数。 因此,原型变为:

void send(const void *object, size_t size);

然后,您需要发送一个整数,因此您将其编码如下:

int foo = 4711;
send(&foo, sizeof (int));

现在,您通过在两个位置指定foo的类型,引入了一种微妙的脚步射击方法。 如果一个更改但另一个没有更改,则代码将中断。 因此,请始终这样做:

send(&foo, sizeof foo);

现在,您已受到保护。 当然,您可以重复变量的名称,但是如果更改它,则很有可能以编译器可以检测的方式破坏该变量。


#5楼

int size = (&arr)[1] - arr;

查看此链接以获取解释


#6楼

如果知道数组的数据类型,则可以使用类似以下内容的方法:

int arr[] = {23, 12, 423, 43, 21, 43, 65, 76, 22};int noofele = sizeof(arr)/sizeof(int);

或者,如果您不知道数组的数据类型,则可以使用类似以下内容的方法:

noofele = sizeof(arr)/sizeof(arr[0]);

注意:只有在运行时未定义数组(例如malloc)并且未在函数中传递数组时,此功能才有效。 在这两种情况下, arr (数组名称)都是一个指针。


#7楼

每个人都使用的宏ARRAYELEMENTCOUNT(x)评估不正确 。 实际上,这只是一个敏感的问题,因为您不能拥有导致“数组”类型的表达式。

/* Compile as: CL /P "macro.c" */
# define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x[0]))ARRAYELEMENTCOUNT(p + 1);

实际评估为:

(sizeof (p + 1) / sizeof (p + 1[0]));

鉴于

/* Compile as: CL /P "macro.c" */
# define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x)[0])ARRAYELEMENTCOUNT(p + 1);

正确评估为:

(sizeof (p + 1) / sizeof (p + 1)[0]);

确实,这与数组的大小没有太大关系。 我刚刚注意到了很多错误,因为他们没有真正观察C预处理器的工作方式。 您总是包装宏参数,而不涉及表达式。


这是对的; 我的例子很糟糕。 但这实际上正是应该发生的情况。 如前所述, p + 1最终将成为指针类型,并使整个宏无效(就像您试图在具有指针参数的函数中使用该宏一样)。

归根结底,在这种特定情况下,错误并不重要(因此,我只是在浪费每个人的时间;烦死了!),因为您没有带有“数组”类型的表达式。 但实际上,我认为关于预处理程序评估的要点很微妙。


#8楼

C中的数组大小:

int a[10];
size_t size_of_array = sizeof(a);      // Size of array a
int n = sizeof (a) / sizeof (a[0]);    // Number of elements in array a
size_t size_of_element = sizeof(a[0]); // Size of each element in array a                                          // Size of each element = size of type

#9楼

最好的方法是例如在以下结构中保存此信息:

typedef struct {int *array;int elements;
} list_s;

实现所有必要的功能,例如创建,销毁,检查相等性以及您需要的所有其他功能。 作为参数传递更容易。


#10楼

执行摘要:

int a[17];
size_t n = sizeof(a)/sizeof(a[0]);

完整答案:

要确定以字节为单位的数组大小,可以使用sizeof运算符:

int a[17];
size_t n = sizeof(a);

在我的计算机上,整数是4个字节长,所以n是68。

为了确定数组中元素的数量,我们可以将数组的总大小除以数组元素的大小。 您可以使用以下类型来执行此操作:

int a[17];
size_t n = sizeof(a) / sizeof(int);

并得到正确的答案(68/4 = 17),但如果类型a改你将有一个讨厌的错误,如果你忘了改变sizeof(int)为好。

因此,首选除数是sizeof(a[0]) ,即数组的第零个元素的大小。

int a[17];
size_t n = sizeof(a) / sizeof(a[0]);

另一个优点是,您现在可以轻松地在宏中参数化数组名称并获得:

#define NELEMS(x)  (sizeof(x) / sizeof((x)[0]))int a[17];
size_t n = NELEMS(a);

#11楼

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

#12楼

值得注意的是, sizeof在处理已衰减为指针的数组值时无济于事:即使它指向数组的开头,但对于编译器,它与指向该数组中单个元素的指针相同数组。 指针不会“记住”用于初始化数组的其他任何信息。

int a[10];
int* p = a;assert(sizeof(a) / sizeof(a[0]) == 10);
assert(sizeof(p) == sizeof(int*));
assert(sizeof(*p) == sizeof(int));

#13楼

#define SIZE_OF_ARRAY(_array) (sizeof(_array) / sizeof(_array[0]))

#14楼

您可以使用sizeof运算符,但不适用于函数,因为它将获取指针的引用,您可以执行以下操作找到数组的长度:

len = sizeof(arr)/sizeof(arr[0])

最初在这里找到的代码: C程序查找数组中元素的数量


#15楼

int a[10];
int size = (*(&a+1)-a) ;

有关更多详细信息,请参见此处和此处 。


#16楼

函数sizeof返回数组在内存中使用的字节数。 如果要计算数组中元素的数量,则应将该数字除以数组的sizeof变量类型。 假设int array[10]; ,如果您计算机中的变量类型整数为32位(或4字节),为了获取数组的大小,您应该执行以下操作:

int array[10];
int sizeOfArray = sizeof(array)/sizeof(int);

#17楼

最简单的答案:

#include <stdio.h>int main(void) {int a[] = {2,3,4,5,4,5,6,78,9,91,435,4,5,76,7,34};//for Example onlyint size;size = sizeof(a)/sizeof(a[0]);//Methodprintf ("size = %d",size);return 0;
}

#18楼

我建议不要使用sizeof (即使可以使用它)来获取数组的两个不同大小中的任何一个,无论是元素数还是字节数,这是我在这里显示的最后两种情况。 对于这两种大小,可以使用下面显示的宏使其更安全。 原因是使代码的意图明显地体现给维护者,乍一看, sizeof(ptr)sizeof(arr)有所不同(这种写法并不明显),因此对于每个阅读代码的人来说,错误都是显而易见的。



有关此主题的重要错误: https : //lkml.org/lkml/2015/9/3/428

我不同意Linus提供的解决方案,即永远不要将数组表示法用作函数的参数。

我喜欢将数组表示法用作将指针用作数组的文档。 但是,这意味着需要采用一种万无一失的解决方案,以便不可能编写错误的代码。

在数组中,我们可能需要知道三种大小:

  • 数组元素的大小
  • 数组中的元素数
  • 数组在内存中使用的字节大小

数组元素的大小

第一个非常简单,我们处理数组还是指针都没有关系,因为它是通过相同的方式完成的。

用法示例:

void foo(ptrdiff_t nmemb, int arr[static nmemb])
{qsort(arr, nmemb, sizeof(arr[0]), cmp);
}

qsort()需要此值作为其第三个参数。


对于其他两个大小(这是问题的主题),我们要确保正在处理数组,如果没有处理,则中断编译,因为如果处理指针,则会得到错误的值。 当编译中断时,我们将能够轻松地看到,我们并没有在处理数组,而是在使用指针,并且我们只需要使用存储变量大小的变量或宏编写代码即可。指针后面的数组。


数组中的元素数

这是最常见的一个,许多答案为您提供了典型的宏ARRAY_SIZE:

#define ARRAY_SIZE(arr)     (sizeof(arr) / sizeof((arr)[0]))

鉴于ARRAY_SIZE的结果通常与ptrdiff_t类型的带符号变量一起使用,最好定义此宏的带符号变量:

#define ARRAY_SSIZE(arr)    ((ptrdiff_t)ARRAY_SIZE(arr))

成员数超过PTRDIFF_MAX数组将为此宏的签名版本提供无效值,但是从读取C17 :: 6.5.6.9来看,类似的数组已经开始发挥作用。 在这些情况下,仅应使用ARRAY_SIZEsize_t

当您将此宏应用于指针时,最新版本的编译器(例如GCC 8)会向您发出警告,因此它是安全的(还有其他方法可确保对较旧的编译器安全)。

它通过将整个数组的字节大小除以每个元素的大小来工作。

用法示例:

void foo(ptrdiff_t nmemb)
{char buf[nmemb];fgets(buf, ARRAY_SIZE(buf), stdin);
}void bar(ptrdiff_t nmemb)
{int arr[nmemb];for (ptrdiff_t i = 0; i < ARRAY_SSIZE(arr); i++)arr[i] = i;
}

如果此函数未使用数组,而是将其用作参数,则先前的代码将无法编译,因此将不可能有错误(假设使用的是最新的编译器版本,或使用了其他技巧) ,我们需要将宏调用替换为以下值:

void foo(ptrdiff_t nmemb, char buf[nmemb])
{fgets(buf, nmemb, stdin);
}void bar(ptrdiff_t nmemb, int arr[nmemb])
{for (ptrdiff_t i = 0; i < nmemb; i++)arr[i] = i;
}

数组在内存中使用的字节大小

通常将ARRAY_SIZE用作前一种情况的解决方案,但这种情况很少被安全地编写,可能是因为它不太常见。

获取此值的常用方法是使用sizeof(arr) 。 问题:与上一个相同; 如果您有一个指针而不是一个数组,您的程序将失败。

该问题的解决方案涉及使用与以前相同的宏,我们知道这是安全的(如果将其应用于指针,它将破坏编译):

#define ARRAY_BYTES(arr)        (sizeof((arr)[0]) * ARRAY_SIZE(arr))

它的工作原理非常简单:它消除了ARRAY_SIZE所做的除法ARRAY_SIZE ,因此,在进行数学取消后,您最终只得到一个sizeof(arr) ,但又增加了ARRAY_SIZE构造的安全性。

用法示例:

void foo(ptrdiff_t nmemb)
{int arr[nmemb];memset(arr, 0, ARRAY_BYTES(arr));
}

memset()需要此值作为其第三个参数。

和以前一样,如果将数组作为参数(指针)接收,则它将无法编译,因此我们必须将宏调用替换为值:

void foo(ptrdiff_t nmemb, int arr[nmemb])
{memset(arr, 0, sizeof(arr[0]) * nmemb);
}

#19楼

对于多维数组,这有点复杂。 人们通常会定义显式宏常量,即

#define g_rgDialogRows   2
#define g_rgDialogCols   7static char const* g_rgDialog[g_rgDialogRows][g_rgDialogCols] =
{{ " ",  " ",    " ",    " 494", " 210", " Generic Sample Dialog", " " },{ " 1", " 330", " 174", " 88",  " ",    " OK",        " " },
};

但是这些常量也可以在编译时使用sizeof求值:

#define rows_of_array(name)       \(sizeof(name   ) / sizeof(name[0][0]) / columns_of_array(name))
#define columns_of_array(name)    \(sizeof(name[0]) / sizeof(name[0][0]))static char* g_rgDialog[][7] = { /* ... */ };assert(   rows_of_array(g_rgDialog) == 2);
assert(columns_of_array(g_rgDialog) == 7);

请注意,此代码可在C和C ++中使用。 对于二维以上的数组,请使用

sizeof(name[0][0][0])
sizeof(name[0][0][0][0])

等等,是无限的。


#20楼

“您介绍了一种微妙的脚下射击方法”

C个“本机”数组不存储其大小。 因此,建议将数组的长度保存在单独的变量/常量中,并在每次传递数组时将其传递,即:

#define MY_ARRAY_LENGTH   15
int myArray[MY_ARRAY_LENGTH];

您应该始终避免使用本机数组(除非您不能这样做,否则请多加注意)。 如果您正在编写C ++,请使用STL的“向量”容器。 “与数组相比,它们提供了几乎相同的性能”,它们的作用要大得多!

// vector is a template, the <int> means it is a vector of ints
vector<int> numbers;  // push_back() puts a new value at the end (or back) of the vector
for (int i = 0; i < 10; i++)numbers.push_back(i);// Determine the size of the array
cout << numbers.size();

请参阅: http : //www.cplusplus.com/reference/stl/vector/

如何确定C语言中数组的大小?相关推荐

  1. error C2057: expected constant expression (C语言中数组的大小可以在程序运行时定义吗? )

    数组的大小可以在程序运行时定义吗? 不.在数组的定义中,数组的大小必须是编译时可知的,不能是在程序运行时才可知的.例如,假设i是一个变量,你就不能用i去定义一个数组的大小: char array[i] ...

  2. 从编译器角度分析C语言中数组名和指针的区别

    从编译器角度分析C语言中数组名和指针的区别 数组名和指针是两个往往很容易让人们混淆的概念,很多人以为数组名就是一个指针,也有很多人知道数组名不同于指针但是仅知道数组名的值不能像指针一样改变. 例如你可 ...

  3. C语言中数组的排序算法详解——选择法、冒泡法、交换法、插入法、折半法

    选择法排序 选择法排序是指:如果要把一个数组从小到大排列,那么就从该数组中依次选择最小的数字来排序.从第一个数字开始,将第一个数字与数组中剩下数字中最小的那一个交换位置,然后将第二个数字与剩下数字中最 ...

  4. c语言中数组的概念及作用,C语言数组的定义及其使用方法

    什么是数组? 在我们学习数组前先让我们介绍一下c语言中数组是什么?数组就是一个个元素按照一定顺序排列的集合.它将数据从最低的内存地址保存到最高的内存地址. 声明一个数组 c语言规定了声明数组的格式: ...

  5. C语言中数组名到底是什么?

    一般情况下,C语言中数组名在表达式中被解读为指向数组首元素的指针 C语言中数组名在表达式中被解读为指向数组首元素的指针, 即数组名在表达式中值为数组首元素的地址.(但有个例外,int a[2];int ...

  6. c语言中数组的变量j是什么,c语言中数组,一般数组

    c语言中数组,一般数组. 1.什么是数组,数组有什么用? 为了方便处理而把类型相同的变量有序地组织起来的一种形式. 类型相同的元素集中起来,在内存上排成一条直线. 2.数组的声明. 元素类型.变量名和 ...

  7. C语言中数组首地址和数组第一个元素的地址有什么区别

    C语言中数组首地址和数组第一个元素的地址关系如下: 1.它们的地址值是相等的. 2.第1个元素的地址如果是p,则p+1就是第2个元素的地址. 3.数组的首地址如果是p,则p+1就跳过这个数组而指向这个 ...

  8. c语言中的下标变量是什么,c语言中数组的下标从什么开始?

    c语言中数组的下标从0开始. 数组中的各元素的存储是有先后顺序的,它们在内存中按照这个先后顺序连续存放在一起.数组元素用整个数组的名字和它自己在数组中的顺序位置来表示. 例如:a[0]就表示名字为a的 ...

  9. c语言中数组的定义与应用

    定义方法: 类型  变量名[元素个数]: 比如: int  a[6]; char b[24]; double c[3]; 注意,c语言中数组的元素个数是不能动态定义的(修改:在c99中已经可以了) 也 ...

最新文章

  1. js 自带的三种弹框
  2. 不可不看的干货——机器人自主系统的技术构建:感知、决策和执行
  3. 网站优化之各个页面的关键词密度的把控
  4. 五种计算机编程语言注定要衰落,牛逼的你怎么看呢???
  5. 3、leetcode 697 数组的度
  6. 【枭·音频】注入灵魂—《暗影火炬城》角色语音后期处理
  7. 华硕vm510l拆电池图解_图解说设备:凯斯CX80C你会买吗?
  8. IOS开发基础之英雄展示完整版
  9. C语言预处理功能——关于字符串化和符号粘贴
  10. C 杂谈之 Apache的模块开发 (一)
  11. python正态分布代码_Tests for normality正态分布检验(python代码实现)
  12. 一个更Swifty核心动画
  13. LGG7刷入第三方ROM,安卓11
  14. [English]英语积累本
  15. SparkContext的初始化(仲篇)——SparkUI、环境变量及调度
  16. 一个奇怪的买鸡蛋问题
  17. 计算机两个屏幕如何连接不上去,电脑连接两台显示器怎么设置?电脑双屏显示的设置步骤...
  18. 高效的java异常(Effective Java Exceptions)
  19. Jenkins - DingTalk
  20. 如何通过几何画板中文版快速等分线段

热门文章

  1. Visual C#组件技巧之深入ComboBox美容
  2. 高效配置Linux代理服务器――Squid
  3. An Implemention of Realtime Gobal Illumination
  4. 关于线段树or 树状树状 在二维平面搞事情!Orz
  5. bosboot -a的作用
  6. js 的函数参数的默认值问题
  7. linux 日志编程(总结)
  8. 实体框架 Code First 迁移命令
  9. 【转载】UltraWinGrid使用心得(C#)
  10. Linux安装Gitlab