Defining digital pins as bytes or integers?

Hi,

while building a POV device I came across an interesting anomaly which I think may be a bug (but I could be missing something).

The issue centres around whether the Arduino pins are defined using bytes or integers. Here's the code:

int ledPin[] = {
  2,3,4,5,6,7,8,9,10,11,12,13,15,16};

void setup()                    // run once, when the sketch starts
{
  for(int i=0; i<sizeof(ledPin); i++){
    pinMode(ledPin[i], OUTPUT);      // sets the digital pins as output
    digitalWrite(ledPin[i], LOW);   // sets the LEDs on  
  }
}

void loop()                     // run over and over again
{
  for(int i=0; i<sizeof(ledPin); i++){
    digitalWrite(ledPin[i], LOW);   // sets the LED on
    delay(100);                  // waits
    digitalWrite(ledPin[i], HIGH);    // sets the LED off
    delay(100);                  // waits
  }
}

This code behaves oddly when uploaded to the Arduino: there is a long pause between loops (the for() loop seems to run for more than 14 time), pin 8 flashes LOW a couple of times during this pause, and after a number of cycles pin 8 ceases to come on.

I though this was hardware related, but then I defined the pin numbers as bytes using the following:

byte ledPin[] = {
  2,3,4,5,6,7,8,9,10,11,12,13,15,16};

and all the problems went away.

Also of note: if I substitute the number 14 for the sizeof() function it will work fine with ints or bytes.

So, is this a bug? something to do with memory allocation?

Hi Scott--

No, it's a misunderstanding of the "sizeof" operator. Sizeof returns the total size in BYTES of its operand. So when you defined ledPin as an array of ints, you created an array of 14 elements, but whose SIZE is actually 28. That means that both of your for loops went way beyond the end of the array, hence the unpredictable results.

It's a common practice to use the clumsy, but correct, expression "sizeof(array)/sizeof(array[0])" to express the number of elements in an array, like this:

for (int i=0; i<sizeof(ledPin)/sizeof(ledPin[0]); ++i)

Good luck with whatever you are working on.

Mikal

Hi Mikal,

that makes sense. Thanks for your help.

Interesting that as the for() loop reads past the end of the array it must write something (through the digitalWrite() function) that permanently turns pin 8 HIGH despite future writes to the contrary.

It's a common practice to use the clumsy, but correct, expression "sizeof(array)/sizeof(array[0])" to express the number of elements in an array

I find it convenient to use a macro for this purpose defined thusly:

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

I am under the presumption that the sizeof() function only returns valid data if the argument passed is current scope(in lack of words/terminology I can not explain myself better).
Is this wrong?

This will not work ?:

class scopetest {
public:
    inline int getSize( int* test ){
        return sizeof(test) / sizeof(test[0]);
    }
};

scopetest sizer();

int testArray[] = { 1,2,3 }; 

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

void loop(){
  Serial.println( sizer.getSize(testArray) );
}

Nope, I'm afraid not. Your getSize function will not work because test is a pointer to the array. There is no way for getSize to know how big the "pointed to" array is. It will always return 1 in Arduino-land because sizeof(test) is 2 and sizeof(test[0]) is also 2. The failure has nothing to do with run-time scope, because sizeof is a compile-time-only operator.

I advise following Don Kinzer's suggestion and defining a macro that returns the number of elements in an array. But make sure you don't pass a pointer to it, or you'll get surprising results.

Mikal

I posted code I hoped would not work. You say that pointers will not work, but in above posted code I am pretty certain that the passed argument to the macro is indeed a pointer. So the function works on pointers, this is why I think it has something to do with scope. Please enlighten me :slight_smile:

I created this problem mainly to warn original poster, that the sizeof funcition is generaly a bad way of getting the size of an array. Or anything that is not a copy of an entire data structure. (as for instance an array never will be, if passed as an argument)
Using a const or maybe a define is a better solution, that is the case in general c++ programming, I dare say.
[I do not know how to express the problem in correct terminology but I do think that scope has something to do with the fact that using sizeof locally works, but not when data is passed down as arguments]

Is it not better to encourage the use of const/defines on array sizes?
I know I would.

This issue is confusing because there is a strong relationship between pointers and arrays in C, but they are not the same thing. Most operations that can be performed using an array name with an index can be also be performed using pointers. But an array name is not the same as a pointer. A pointer is a variable and in the arduino has a size of two bytes. An array name is not a variable, it's a C type and its size is determined by the compiler when the array is declared. But when you pass a reference to an array into a function, what is passed is a pointer to the first element of the array. Thus, within the scope of the function, because the reference is a pointer, its sizeof will be 2 bytes.

I hope that helps

This issue is confusing because there is a strong relationship between pointers and arrays in C, but they are not the same thing. Most operations that can be performed using an array name with an index can be also be performed using pointers.

I thought that in fact all operations can be done, is this wrong? If not, why would one separate between a pointer and an array name (which does point to the first element, and would by that fact qualify as a pointer, at least it seems logical for me that way but... hmm)

But an array name is not the same as a pointer. A pointer is a variable and in the arduino has a size of two bytes. An array name is not a variable, it[ch8217]s a C type and its size is determined by the compiler when the array is declared.

Are you certain that you did not mean "An array name is not a variable, it[ch8217]s a C type" because that I agree with. Or is there something that I'm missing?

But when you pass a reference to an array into a function, what is passed is a pointer to the first element of the array. Thus, within the scope of the function, because the reference is a pointer, its sizeof will be 2 bytes.

I do not argue that the reference is in scope, but the value that it refers is ''not in scope" or rather, it does not know if it is an array of bytes or ints. And this is my point exactly, and why I began to question this.
I think it is better to encourage the use of defines/constants since that is a much more robust way of handeling array lengths, rather than the sizeof operator.

I must emphesize that I may not use the right words, and that I question this topic because I want to learn more, and occationaly come to teach something to someone in return.
It does seem that I cannot explain myself, because my example program 4 post above explicitly states "this program will not work" [EDIT: I see I accidentaly inserted a '?' prosumably becase I wrote the example in forum, and was uncertain it would compile at all] and was aimed towards original poster, in case he planned to make this into a library, the sizeof would not work properly if an array was to be passed down as an argument.