Sizeof arrays

Hi people, i'm a newbie and i dont understand how it work's (sizeof).
If I have this code:

uint8_t values[] = {1,3,5,7,9,11,13};
uint8_t ex_1;
uint8_t ex_2;
setup(){
   ex_1 = sizeof(values); //Here I have the size of the array, ok!
   setvalues(values);
}
loop(){
//
}
void setvalues(uint8_t val[]){
  ex_2 = sizeof(val);  //But here, the function sizeof return 2. Why?
}

Thanks in advance.

You passed the function a pointer, so you're getting the size of the pointer (2 bytes). Send the size as a function argument:

setvalues(values, sizeof(values));
...
void setvalues(uint8_t val[], size_t ex_2){
  ...
}

But when i put this

setvalues(values)

I send the array or the pointer? And all variables is uint8_t, so, it have 1byte, is right?
I wanna get the size of array inside the fuction, using only: function(array) How I can do this?
Sorry for my bad english and thank's again.

wizarcl:
I send the array or the pointer? And all variables is uint8_t, so, it have 1byte, is right?

An array is represented by a pointer to the first object in the array. When you pass an array as an argument to a function, you are passing a pointer to the first object in the array. The function doesn't care if it's simply a pointer to a single variable, or a collection of variables that constitute an array.

I wanna get the size of array inside the fuction, using only: function(array) How I can do this?

You can't, aside from defining the array to be one element more, and putting a "stop character" at the end. This is why you can do it for strings and strlen().

Ok, but in this case, the size of pointer is 1byte or 2 bytes? Because I declared the values like uint8_t.

wizarcl:
Ok, but in this case, the size of pointer is 1byte or 2 bytes? Because I declared the values like uint8_t.

A single byte point would give you 255 possible addresses to point to; Arduino's has more memory than that.

lol... I know... Arduino's have more memory...
:stuck_out_tongue:

But i dont understand why the sizeof inside function return 2 (2bytes) like you said.

so you're getting the size of the pointer (2 bytes)

Because i declared all like 1 byte.

A single byte point would give you 255 possible addresses to point to

Very close. :wink:

But i dont understand why the sizeof inside function return 2 (2bytes

Because that's the size of a pointer

wizarcl:
But i dont understand why the sizeof inside function return 2 (2bytes) like you said.

so you're getting the size of the pointer (2 bytes)

Because i declared all like 1 byte.

Because a pointer doesn't contain actual data, it contains an address. If the pointer was only one byte wide, it could only contain 256 possible addresses. That means you could only have 256 bytes of memory (assuming the memory was byte addressable).

The size of a pointer in an ATmega328 (and many others) is 2 bytes. Think about it, you have 2kB of RAM, what is the fewest number of bytes you need to address the whole lot - the answer is 2.

sizeof() is not so much a function as it is a compile time calculation. If you call:

sizeof(values);

The compiler/pre-processor/whatever looks up the size of values. It is know that it is an array of 7 bytes, so sizeof() returns (7x1)=7.

Inside your function you call

sizeof(val);

So how big is it. Well it could be 7 bytes as before, but the compiler can't know that. What if you were for example to call:

byte newArray[100];
setvalues(newArray);

This time you have passed an array of 100 bytes, not 7. How can the compiler then work out what size it is supposed to be if it can change depending on when the function is called while the program is running.
As it doesn't know the size of the array, it defaults the returning the size of what you have declared which is really just

setValues(byte* val);

a byte* is a pointer, and how big is a pointer? 2 bytes. Why? see the first line of this post.

I believe I am right in saying that if you try this:

void setvalues(uint8_t val[7]){
  ex_2 = sizeof(val);  //But here, the function sizeof return 2. Why?
}

Then sizeof() would return 7 (I think). But then what happens if you pass a reference to an array of 2 bytes?

I guess understand, :grin:
So, all undeclared pointers have 2bytes of size?

How can you have an "undeclared pointer"?

lol....
sorry, is true. I understand now.
So, i can't get the sizeof array inside my function like i wanna..?
Only using:

You passed the function a pointer, so you're getting the size of the pointer (2 bytes). Send the size as a function argument:

setvalues(values, sizeof(values));

...
void setvalues(uint8_t val, size_t ex_2){
  ...



}

Thanks for your patience…
I was trying do this… :

uint8_t INPUTS[] = {2,4,6,8};
uint8_t OUTPUTS[] = {1,3,5,7,9,11,13};

void setup(){
  Serial.begin(9600);
  pinModeAutomatic(INPUTS,INPUT);
  pinModeAutomatic(OUTPUTS,OUTPUT);
}

void loop(){
//
}

void pinModeAutomatic(uint8_t pins[], uint8_t MODE)
{	
	uint8_t i; 
	for(i=0;i<sizeof(pins);i++){
		pinMode(pins[i],MODE);
	}
}

I will try do otherwise.
Tks!

Again…

You have just used sizeof() on a pointer in a function. This time you have done sizeof(pins). It will return 2.

Do this:

void pinModeAutomatic(uint8_t pins[], uint8_t mode, byte length){
  uint8_t i; 
  for(i=0;i<length;i++){
    pinMode(pins[i],mode);
  }
}

And accept it is the only way.

EDIT:
I suppose if you really must, you could do this:

#define pinModeAutomatic(p, m) _pinModeAutomatic(p,m,sizeof(p))

uint8_t inputs[] = {2,4,6,8};
uint8_t outputs[] = {1,3,5,7,9,11,13};

void setup(){
  Serial.begin(9600);
  pinModeAutomatic(inputs,INPUT);
  pinModeAutomatic(outputs,OUTPUT);
}

void loop(){
//
}

void _pinModeAutomatic(uint8_t pins[], uint8_t MODE, byte length){
  uint8_t i; 
  for(i=0;i<length;i++){
    pinMode(pins[i],MODE);
  }
}

But it’s just asking for trouble later on.
(And don’t make ‘ALLCAPS’ variable names!)

length needs a type

Thank you so much Tom.

Arrch:
length needs a type

So it does, I was too busy watching Tennis to pay enough attention to what I wrote.

Thanks again guys…
I have one more question, i think, i can’t use:

#define pinModeAutomatic(p, m) pinModeAutomatic(p,m,sizeof(p))

because:

sketch_jul05a.ino:6:67: error: macro "pinModeAutomatic" passed 3 arguments, but takes just 2
sketch_jul05a.ino:16:67: error: macro "pinModeAutomatic" passed 3 arguments, but takes just 2
sketch_jul05a:6: error: variable or field 'pinModeAutomatic' declared void
sketch_jul05a.ino: In function 'void setup()':
sketch_jul05a:8: error: 'pinModeAutomatic' was not declared in this scope
sketch_jul05a.ino: At global scope:
sketch_jul05a:16: error: function definition does not declare parameters

So, i change the names and it work’s:

#define definePins(p, m) pinModeAutomatic(p,m,sizeof(p))

uint8_t INPUTS[] = {2,4,6,8};
uint8_t OUTPUTS[] = {1,3,5,7,9,11,13};

void setup(){
  Serial.begin(9600);
  definePins(INPUTS,INPUT);
  definePins(OUTPUTS,OUTPUT);
}

void loop(){
//
}

void pinModeAutomatic(uint8_t pins[], uint8_t MODE, uint8_t length){
  uint8_t i; 
  for(i=0;i<length;i++){
    pinMode(pins[i],MODE);
  }
}

It’s corret?

You're right, it doesn't work, forgot #define and function had to be slightly different names.

(Again, I recommend you DONT declare variable names with ALLCAPITALLETTERS as they should be left to #define constants. If you aren't careful you could find yourself declaring a variable whose name is the same as an existing #define)