A function to get the number of variables in an array?

hi

I've been trying to find a way to get the number of variables from an array an set it to an integer.

e.g. a excerpt from the array tutorial http://arduino.cc/en/Tutorial/Array

int ledPins[] = {
2, 7, 4, 6, 5, 3 }; // an array of pin numbers to which LEDs are attached
int pinCount = 6; // the number of pins (i.e. the length of the array)

Is there a function that would set the pinCount integer to the number of variables in the ledPins array?

pinCount = sizeof (ledPins) / sizeof (ledPins[0]);

Note that this only works when both variables have exactly the same scope.

thanks!

As far as I understand the compiler will calculate the pinCount during compiling and write the value to flash memory, i.e. the sizeOf() utility can not be used to calculate a value during run time?

sizeof can only give you the total size of the object. For example, it cannot tell you how many cells of an array are actually being used.

You can use it during run time, but it will just give the same answers as it did during compile time. for example, this code:

int *p;
p = malloc(1000);
int sp = sizeof(p);

will set sp to the size of the int pointer, not the size of the malloc'd array. The same thing happens in function calls, since C is call by value.

Same idea, but I usually use the following construct

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

then in code use (for example)

int  arr[] = {1, 2, 3, 4, 5, 6};
for (uint8_t i=0; i<ARRAY_SIZE(arr); i++)
  // do something

I find it easier to read the intent of the sizeof() statements when scanning code.

As already stated, this is resolved at compile time and so does not suit dynamically allocated arrays.

KeithRB:
will set sp to the size of the int pointer, not the size of the malloc'd array. The same thing happens in function calls, since C is call by value.

That's because the type of p in your example is a pointer, not an array of known length. (That's also why it typically happens in functions - not because the value is copied, but because the type of the formal argument is an array of unspecified length - semantically equivalent to a pointer - rather than an array of known length.)

Right, how do you malloc an "array of known length" that would be known at run time vs compile time?

You cannot malloc() at compile time because you need to call a function, which only happens when the code starts running. Declaring an array like a[10] is how you allocate the memory at compile time.

KeithRB:
Right, how do you malloc an "array of known length" that would be known at run time vs compile time?

I don't recall ever doing it, but I imagine it'd be possible to do it indirectly (via a pointer) and declare the pointer as a pointer-to-array-of-specified-length. I suppose the length of the array would then be implied by the type of the pointer used to access it. It may be possible to clean up the use of pointers by using reference types. Alternatively, declare the array in a struct or as an instance field in a class that is created dynamically - you'd end up with an array of specified length which is allocated dynamically. From the point of view of knowing the array length, what matters is the type of the value, not where in memory it happens to reside or when it was allocated. In all these cases, the length of the array would be a compile time constant.

Sort of related, you can declare automatic array variables with lengths provided at runtime, but these are not allocated by malloc.

here is a small example with an array consisting of two arrays

int array[] = {1,2,3,4,5,6};
int array2[] = {22,33,44,55};

int* BBB[] = {array, array2};

byte sizeOfBBB= sizeof(aa) / sizeof(aa[0]);

is it possible to find out the length of an array that is within the BBB array?

No, you can't deduce from a pointer how large the thing it is pointing to, is.

You might have a second array, as in this example:

// number of items in an array
#define NUMITEMS(arg) ((unsigned int) (sizeof (arg) / sizeof (arg [0])))

int array[] = {1,2,3,4,5,6};
int array2[] = {22,33,44,55};

int* BBB[]         = {array, array2};
int BBB_lengths [] = { NUMITEMS (array), NUMITEMS (array2) };

Could you please explain what arg stands for and what unsigned int does?

Moderator edit: tags corrected (hopefully)

The type of "sizeof" is "size_t", so the "unsigned int" is just a cast.
"arg" is simply what will get substituted when the macro is invoked.

#define NUMITEMS(arg) ((unsigned int) (sizeof (arg) / sizeof (arg [0])))

so if I write size = NUMITEMS(x); the compiler sees size = ((unsigned int) (sizeof (x) / sizeof (x [0])))

Unless you use 'malloc' or 'new' to create dynamic memory, this information is readily available by the compiler state. It knows the size of arrays even when there is no clear cut way to grab the info.

Here is a method that causes the compiler to provide the answer, rather than computing the value.

EDIT: The added bonus is it has protection against non array pointers, unlike the defines above.

template< typename T, size_t N > size_t ArraySize( T (&)[N] ){ return N; }

int ledPins[] = {
  2, 7, 4, 6, 5, 3 };


void setup()
  {
    Serial.begin( 9600 );
    Serial.print( "Array Size: " );
    Serial.println( ArraySize( ledPins ) );
  }

pYro_65:
Unless you use 'malloc' or 'new' to create dynamic memory

And even if you did use dynamic memory allocation, you had to ask for a certain amount, so you should know how big it is.

a related question,

I decided to try multidimensional arrays, but I'm getting some weird output from the Serial.print

int macros[][2] = {
(1,2,3,4,5,6),
(33,55,77)
};

void setup() {
Serial.begin(9600);
}

void loop() {

int Value01 = (macros[0][1]);
int Value02 = (macros[1][0]);
Serial.print("Value01 = ");
Serial.print(Value01);
Serial.println();
Serial.print("Value02 = ");
Serial.print(Value02);
Serial.println();
delay(1000);
}

I expected to get:

Value01 = 2
Value02 = 33

but instead I'm getting:
Value01 = 77
Value02 = starts with 0 and then goes through what a series of integers read from some memory location outside of the array.

Not sure what I'm doing wrong...?

Look very carefully at the declaration of "macros".
Then look very carefully at the initialization of "macros"

pYro_65:
Here is a method that causes the compiler to provide the answer, rather than computing the value.

EDIT: The added bonus is it has protection against non array pointers, unlike the defines above.

template< typename T, size_t N > size_t ArraySize( T (&)[N] ){ return N; }

Yes, very cunning. Except it doesn't return a constant so it can't be used here:

template< typename T, size_t N > size_t ArraySize(T (&)[N] ){ return N; }
int foo [] = { 5, 6, 7, 8, 9 };
int bar [ ArraySize (foo) ];   // make another array the same size

Error:

sketch_mar12c:3: error: array bound is not an integer constant

The NUMITEMS method works there.

This is becoming a very esoteric topic for what is usually a non-issue in code - either you know the size of the memory block at compile time (because it is a constant) or you allocate the memory by telling the libraries how much you want (in which case you know before you ask).

Getting back to basics - what are you trying to achieve?

Sorry, marco_c but it was getting interesting. :slight_smile:

@OP: You need multiple braces as PaulS is hinting:

int macros[][2] = {
  {1,2,3,4,5,6},   
  {33,55,77} 
};

Not round brackets. Now that gives an error, but you can take it from there.