1. In this array: float arr[] = { 22.5, 31.16, 58.0, 102.11, 99.0 };, we have 5 members (aka elements) where each member is a data of type float.
2. When we declare a variable like this (with float keyword): float x = 31.16;, the Compiler saves four bytes data (against the value of the variable x) into four consecutive memory locations as per binary32 convention of IEEE-754 standard. In this case (for the value of 31.16), the Compiler saves: 41 F9 47 AE (41 is the Most Significant Byte). In case, the OP wishes to know I have given below a sketch that obtains the binary32 formatted value of a float variable.
void setup()
{
Serial.begin(9600);
float x = 31.16;
unsigned long *p;
p = (unsigned long*) &x;
unsigned long m = *p;
Serial.println(m, HEX); //Shows: 41F947AE
while(1);
}
3. From Step-2, we can conclude that the array of Step-1 contains 5x4 = 20 byte data which can be known by executing these code:
byte n = sizeof(arr)
Serial.print(n); //shows 20
4. Having known before hand that the float type data is represented by 4-byte value, we could easily calculate the element/member size of the array of Step-1 by executing this instruction:
byte numberOfElements = sizeof(arr)/4; //sizeof(arr)(=size arr) returns number of bytes in arr
Serial.print(numberOfElements); // shows 5
OR
size_t numberOfElements = sizeof(arr)/4;
Serial.print(numberOfElements); // shows 5
size_t is an unsigned integer data type which is defined in various header files like: <stddef.h>, <stdio.h>, <stdlib.h>, <string.h>, < time .h>, <wchar.h> chevron_right. It's a type which is used to represent sizes of objects in bytes, hence it can be returned by the sizeof operator.
However, in the sketch of the OP, we have this code:
size_t numberOfElement = sizeof arr/sizeof *arr;
==> byte numberOfElements = sizeof(arr) / sizeof(*arr);
5. Let us see, how sizeof(*arr); does return 4.
Let us remember the fact that the array name (here arr) always points to the first element/member (arr[0]) of the array. Therefore (as has been shown in the previous posts),
Serial.println(sizeof(*arr)); //shows: 4
==> Serial.println(sizeof(arr[0])); //shows: 4
BTW: There is an advantage of using sizeof(*arr); instead of using the fixed value 4. We have another keyword double which is used to declare/define 64-bit (double precision) floating point number where each element of the array is 8-byte long. So, if we use sizeof(*arr);, there is no need to look for 4 in the sketch (there could be many 4s; it is which 4 that we are looking for) and change it to 8; instead, we just change the data type form float to double. The codes remain dynamic. For example (testable on Arduino DUE):
double arr[] = { 22.5, 31.16, 58.0, 102.11, 99.0 };
byte numberOfElement = sizeof(arr)/sizeof(*arr);
Serial.println(numberOfElements); //shows: 5