Pages: [1]   Go Down
Author Topic: Trying to get the size of an array of bytes.  (Read 720 times)
0 Members and 1 Guest are viewing this topic.
Dendermonde/Belgium
Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello everybody,

I'm trying to get the size of an array of bytes this way:

Code:
byte t_size[] = {255, 255, 255, 255};
Save(t_size, 0);

boolean Save(byte* data, int offset) {
  Serial.println(sizeof(data));
}

It returns 2, while

Code:
byte t_size[] = {255, 255, 255, 255};
Serial.println(sizeof(t_size));

returns 4

Can someone explain me why, and eventually point me in the right direction?

Thanks a lot!
--
Wim
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 224
Posts: 13915
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
boolean Save(byte* data, int offset) {
  Serial.println(sizeof(data));
}

returns the size of the pointer to byte

Code:
byte t_size[] = {255, 255, 255, 255};
Serial.println(sizeof(t_size));

returns teh size of the array

sizeof() is calculated compile time and in the first code the compiler can only see and calculate the size of the pointer.
(I learned this recently the hard way ... again smiley-wink
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Left Coast, USA
Offline Offline
Sr. Member
****
Karma: 7
Posts: 499
Sometimes I just can't help myself.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


size of an array of bytes this way:

Code:
...

boolean Save(byte* data, int offset) {
  Serial.println(sizeof(data));
}

ICan someone explain me why, and eventually point me in the right direction?


robtillaart told you why your example can not work as written.

Here's the "right direction."

Since the function can not know the size of the array unless you tell it, define the function with another parameter that the calling function can use to convey the size:

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

// A "global" array of bytes
byte a[5] ={1, 2, 3, 4, 5}; // Initialized once when the program is started

void loop()
{
    // A "local" array of bytes.
    byte b[3] = {6, 7, 8};  // Re-initialized every time through the loop
    
    // At this point it knows the size of the array, since it can "see" the array.
    Serial.print("In loop: sizeof(a) = ");
    Serial.println(sizeof(a));
    
    // When you use the name of an array as an argument in a function call
    // it is passing a pointer whose value is the address of the
    // first element of the array.
    Serial.print("Calling printArray for a: ");
    printArray(a, sizeof(a));
    Serial.println();
    
    // At this point it knows the size of the array, since it can "see" the array.
    Serial.print("In loop: sizeof(b) = ");
    Serial.println(sizeof(b));
    
    Serial.print("Calling printArray for b: ");
    printArray(b, sizeof(b));
    Serial.println();

    ++a[0];
    ++b[1];
    
    delay(10000);
    Serial.println();
}

// There is no way (no way) that the function can
// know the size of the array unless you tell it.
// The most general way is with a parameter.
//
// The function can not "see" the array but it can "see"
// the memory whose address is whatever its first argument
// is pointing to.
//
void printArray(byte *x, int siz)
{
    for (int i = 0; i < siz; i++) {
        Serial.print(" ");
        Serial.print(x[i], DEC);
    }
}

Output:

In loop: sizeof(a) = 5
Calling printArray for a:  1 2 3 4 5
In loop: sizeof(b) = 3
Calling printArray for b:  6 7 8

In loop: sizeof(a) = 5
Calling printArray for a:  2 2 3 4 5
In loop;: sizeof(b) = 3
Calling printArray for b:  6 7 8



« Last Edit: June 02, 2011, 08:21:42 am by davekw7x » Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 309
Posts: 26509
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
printArray(a, sizeof(a));
You should ALWAYS use "sizeof (a) / sizeof (a[0])" to give the number of elements in the array.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Left Coast, USA
Offline Offline
Sr. Member
****
Karma: 7
Posts: 499
Sometimes I just can't help myself.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
printArray(a, sizeof(a));
You should ALWAYS use "sizeof (a) / sizeof (a[0])" to give the number of elements in the array.
May be good advice in general.

However for the specific example to which I was responding:

The byte type is unsigned char.

And, according to C and C++ standards documents:

sizeof(char) and sizeof(unsigned char) are ALWAYS 1.


Regards,

Dave
« Last Edit: June 02, 2011, 09:03:54 am by davekw7x » Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 309
Posts: 26509
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Can't disagree in general, but try overloading "printArray" with an "int" array method.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Left Coast, USA
Offline Offline
Sr. Member
****
Karma: 7
Posts: 499
Sometimes I just can't help myself.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Can't disagree in general, but try overloading "printArray" with an "int" array method.
The function looks about the same:
Code:
// The "siz" parameter is the number of elements in the array
void printArray(int *x, int siz)
{
    for (int i = 0; i < siz; i++) {
        Serial.print(" ");
        Serial.print(x[i]);
    }
}

The calling function must determine the number of elements in the array, and your advice is one way for a function that can see the array can determine the size.  

However...

It's not necessary to use sizeof() at all:
Code:
void loop()
{
    const int bSize = 3;
    
    // A "local" array of ints.
    int b[bSize] = {6, 7, 8};  // Re-initialized every time through the loop
    
    // When you use the name of an array as an argument in a function call
    // it is passing a pointer whose value is the address of the
    // first element of the array.
    Serial.print("Calling printArray(b, bSize) :");
    printArray(b, bSize);
    Serial.println();
.
.
.

Of course I could have used sizeof(b)/sizeof(b[0]) to let the compiler calculate the number of elements in the array at compile time, but I almost always use the method that I showed here:  Specify the number of elements in the array by using a constant in the definition.  Then use that constant wherever you need it.  (Note that there is no code size or run time overhead for using a constant like this, just as there is no code size or run time overhead for using sizeof() in an expression.)

Since the Original Poster asked about sizeof(), I was trying to respond to his question and I showed that sizeof() gave the number of bytes in the byte array, provided that the program can "see" the array at that point.  It might have been more instructive to go into a more general example (using an array of ints or floats or some such thing) that could use your advice to determine the number of elements, but my point is something that you already knew but the Original Poster apparently did not.

Namely that a function that works on an array can not know the how many elements are in the array unless you tell it.  I gave a general method of telling it: Define the function to have a parameter that tells it the number of elements in the array.


Regards,

Dave

Footnote:
The thing that we all want to avoid is "hard-coding" the array size at multiple points in the program:
Code:
void loop()
{  
    // A "local" array of ints.
    int b[3] = {6, 7, 8};  // Re-initialized every time through the loop
    
    
    // When you use the name of an array as an argument in a function call
    // it is passing a pointer whose value is the address of the
    // first element of the array.
    Serial.print("Calling printArray(b, 3) :"); // If you change the array size, don't forget to change this too!
    printArray(b, 3);
    Serial.println();

That just increases the probability of a "forgetful" error in case we want to modify the array to have more or fewer elements.  By using the sizeof(b)/sizeof(b[0]) expression or by using the const stuff I showed, we don't have to remember to change the siz parameter every place we call the function.

I mean, I could have put all of this stuff in my original response, but...
« Last Edit: June 15, 2011, 02:32:31 pm by davekw7x » Logged

Dendermonde/Belgium
Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello everybody,

thanks for the hints and explanations, it's highly appreciated  smiley

What I wanted to do in the first place is to create a "save" function that saves some data to the EEPROM:
 - an IP address, a netmask and a gateway (all 4 bytes)
 - an integer (2 bytes)

I just wanted that the save function was able to determine the length of the data to be saved.

I think I just pass the length of the array to the save function!

Thanks a lot!
--
Wim
Logged

Pages: [1]   Go Up
Jump to: