Passing a boolean to a constructor

Here is a part of code from my BooleanArray class:

class BooleanArray{

  protected : int arrayLength;
              boolean* arrayPointer;
   
  public : BooleanArray(boolean booleanValue);
           ~BooleanArray();
           
           void set(int intIndex ,boolean booleanValue);
           String toString(int intStart,int intStop);
           String toString();

};

BooleanArray::BooleanArray(boolean booleanValue)
{
  arrayLength = 1;
  arrayPointer = (boolean *)calloc(1,sizeof(boolean));
  set(0,booleanValue);
}

BooleanArray::~BooleanArray()
{
  if(arrayPointer){
     free(arrayPointer);
  }
}

void BooleanArray::set(int intIndex, boolean booleanValue)
{
  if(arrayPointer && intIndex >= 0 && intIndex < arrayLength){
    arrayPointer[intIndex] = booleanValue;
  }
}

String BooleanArray::toString(int intStart,int intStop)
{
  if(arrayLength == 0 || intStart > intStop){return "{}";}
  String OUT = "{";
  for(int i = intStart; i <intStop;i++){
    if(get(i) == true){OUT = OUT + "true";}else{OUT = OUT + "false";}
    if(OUT.length() > 200){int k = intStop - i - 1 ;OUT = OUT + "}[";OUT = OUT + k;OUT = OUT +"_MORE_VALUES]";return OUT;}
    if(i != intStop - 1){OUT = OUT +",";}
  }
  OUT = OUT + "}";
  return OUT;
}

String BooleanArray::toStringIO()
{
  return toStringIO(0,length());
}

When I run this code:

void setup(){

  Serial.begin(9600);
  
  boolean B = true;
  BooleanArray array(B);
  Serial.println(array.toString());
  
}
void loop(){}

The arduino prints over the Serial port: {true} , as expected
but when I run this code:

void setup(){

  Serial.begin(9600);

  BooleanArray array(true);
  Serial.println(array.toString());
  
}
void loop(){}

I get this: {false}
How is this posible since I pass 2 times true to the constructor?
Any ideas for fixing this problem?

Thank you,
Knockstaart

String BooleanArray::toStringIO()
{
  return toStringIO(0,length());
}

Is this meant to be a recursive call?

String BooleanArray::toString(int intStart,int intStop)
{
  if(arrayLength == 0 || intStart > intStop){return "{}";}
  String OUT = "{";

// Snip

  return OUT;
}

Returning a value that is allocated on the stack is fine for simple type, but not for class instances.

In wiring.h:

#define true 0x1

Literals are interpreted as ints, unless otherwise directed. So, in the one case, you are passing a boolean (8 bites) to the function, which expects an 8 bit value.

In the other case, you are passing 16 bits to a function that expects 8 bits. Whether it is the first 8 bits or the second 8 bits that gets used is a function of how the int is pushed onto the stack. Most likely, it is the first 8 bits (that are 0) that are used, rather than the last 8 bits (that are 1).

It's always nice to post code that compiles and demonstrates the problem, not snippets. This compiles:

class BooleanArray{

protected : 
  int arrayLength;
  boolean* arrayPointer;

public : 
  BooleanArray(boolean booleanValue);
  ~BooleanArray();

  void set(int intIndex ,boolean booleanValue);
  boolean get(int intIndex);
  String toString(int intStart,int intStop);
  String toString();

};

BooleanArray::BooleanArray(boolean booleanValue) : 
arrayPointer (NULL)
{
  arrayLength = 1;
  arrayPointer = (boolean *)calloc(1,sizeof(boolean));
  set(0,booleanValue);
}

BooleanArray::~BooleanArray()
{
  if(arrayPointer){
    free(arrayPointer);
  }
}

void BooleanArray::set(int intIndex, boolean booleanValue)
{
  if(arrayPointer && intIndex >= 0 && intIndex < arrayLength){
    arrayPointer[intIndex] = booleanValue;
  }
}

boolean BooleanArray::get(int intIndex)
{
  if(arrayPointer && intIndex >= 0 && intIndex < arrayLength){
    return arrayPointer[intIndex];
  }
}

String BooleanArray::toString(int intStart,int intStop)
{
  if(arrayLength == 0 || intStart > intStop){
    return "{}";
  }
  String OUT = "{";
  for(int i = intStart; i <intStop;i++){
    if(get(i) == true){
      OUT = OUT + "true";
    }
    else{
      OUT = OUT + "false";
    }
    if(OUT.length() > 200){
      int k = intStop - i - 1 ;
      OUT = OUT + "}[";
      OUT = OUT + k;
      OUT = OUT +"_MORE_VALUES]";
      return OUT;
    }
    if(i != intStop - 1){
      OUT = OUT +",";
    }
  }
  OUT = OUT + "}";
  return OUT;
}


void setup(){

  Serial.begin(115200);

  BooleanArray array(true);
  Serial.println(array.toString(0, 1));

  BooleanArray foo(false);
  Serial.println(foo.toString(0, 1));

}
void loop(){
}

It prints:

{true}
{false}

So, something in what you haven't shown us is responsible.

PaulS:
Returning a value that is allocated on the stack is fine for simple type, but not for class instances.

Paul, the compiler will create a temporary instance, invoke the operator=, and return that instance. That is OK in this case. Effectively you are returning a copy.

Having said that, your (knockstaart's) toString function is incredibly wasteful of memory. By concatenating strings like that you are very likely to fragment and run out of memory quickly. And making another copy to be returned to the caller is not going to help.

This code does compile and shows the problem
all the other constructors in the class are included:

class BooleanArray{

  protected : int arrayLength;
              boolean* arrayPointer;
   
  public :  BooleanArray();
            BooleanArray(int intLength);
            BooleanArray(int intLength, boolean * boolList);
            BooleanArray(int intLength, boolean booleanValue);
            BooleanArray(boolean booleanValue);
            BooleanArray(int intLength, int intValue);
            BooleanArray(const BooleanArray & objectBooleanArray);
            BooleanArray(String StringValue);
            ~BooleanArray();
           
           void set(int intIndex ,boolean booleanValue);
           String toString(int intStart,int intStop);
           String toString();
           boolean get(int intIndex);
           int length();

};


BooleanArray::BooleanArray()
{
  arrayLength = 0;
  arrayPointer = (boolean *)calloc(1,sizeof(boolean));
}

BooleanArray::BooleanArray(int intLength)
{
  if(intLength < 0){intLength = 0;}
  if(intLength >= 0){arrayLength = intLength;}
  if(intLength > 0){
    arrayPointer = (boolean *)calloc(intLength,sizeof(boolean));
    for(int i = 0;i < arrayLength;i++){
      set(i,false);
    }
  }
}

BooleanArray::BooleanArray(int intLength, boolean * boolList)
{
  if(intLength < 0){intLength = 0;}
  if(intLength >= 0){arrayLength = intLength;}
  if(intLength > 0){
    arrayPointer = (boolean *)calloc(intLength,sizeof(boolean));
    for(int i = 0;i < arrayLength;i++){
      set(i,boolList[i]);
    }
  }
}

BooleanArray::BooleanArray(int intLength, int intValue)
{
  if(intLength < 0){intLength = 0;}
  if(intLength >= 0){arrayLength = intLength;}
  if(intLength > 0){
    arrayPointer = (boolean *)calloc(intLength,sizeof(boolean));
    for(int i = 0;i < arrayLength;i++){
      set(i,false);
    }
  }
}

BooleanArray::BooleanArray(int intLength, boolean booleanValue)
{
  if(intLength < 0){intLength = 0;}
  if(intLength >= 0){arrayLength = intLength;}
  if(intLength > 0){
    arrayPointer = (boolean *)calloc(intLength,sizeof(boolean));
    for(int i = 0;i < arrayLength;i++){
      set(i,booleanValue);
    }
  }
}

BooleanArray::BooleanArray(boolean booleanValue)
{
  arrayLength = 1;
  arrayPointer = (boolean *)calloc(1,sizeof(boolean));
  set(0,booleanValue);
}

BooleanArray::BooleanArray(const BooleanArray & objectBooleanArray)
{
  arrayLength = objectBooleanArray.arrayLength;
  arrayPointer = (boolean *)calloc(arrayLength,sizeof(boolean));
  for(int i = 0;i < arrayLength;i++){
    set(i,objectBooleanArray.arrayPointer[i]);
  }
}

BooleanArray::BooleanArray(String StringValue)
{
  boolean OK = true;
  for(int i = 0;i < StringValue.length();i++){if(StringValue.charAt(i) != 48 && StringValue.charAt(i) != 49){OK = false;}}
  if(OK == false){
    arrayLength = 0;
    arrayPointer = 0;
    return;
  }else{
    arrayLength = StringValue.length();
    arrayPointer = (boolean *)calloc(arrayLength,sizeof(boolean));
    for(int i = 0;i < arrayLength;i++){
      if(StringValue.charAt(i) == 48){set(i,false);}else{set(i,true);}
    }    
  } 
}

BooleanArray::~BooleanArray()
{
  if(arrayPointer){
     free(arrayPointer);
  }
}

void BooleanArray::set(int intIndex, boolean booleanValue)
{
  if(arrayPointer && intIndex >= 0 && intIndex < arrayLength){
    arrayPointer[intIndex] = booleanValue;
  }
}

String BooleanArray::toString(int intStart,int intStop)
{
  if(arrayLength == 0 || intStart > intStop){return "{}";}
  String OUT = "{";
  for(int i = intStart; i <intStop;i++){
    if(get(i) == true){OUT = OUT + "true";}else{OUT = OUT + "false";}
    if(OUT.length() > 200){int k = intStop - i - 1 ;OUT = OUT + "}[";OUT = OUT + k;OUT = OUT +"_MORE_VALUES]";return OUT;}
    if(i != intStop - 1){OUT = OUT +",";}
  }
  OUT = OUT + "}";
  return OUT;
}

String BooleanArray::toString()
{
  return toString(0,length());
}

int BooleanArray::length(){return arrayLength;}

boolean BooleanArray::get(int intIndex)
{
  if(arrayPointer && intIndex >= 0 && intIndex < arrayLength){
     return arrayPointer[intIndex];
  }else{
     return false;
  }
}


void setup(){

  Serial.begin(9600);
  
  boolean B = true;
  BooleanArray array1(B);
  Serial.println(array1.toString());
  BooleanArray array2(true);
  Serial.println(array2.toString());
  
}
void loop(){}

expected output :

{true}
{true}

recieved output:

{true}
{false}

Any idea what might cause this problem?
Thank you,
knockstaart

Well, you have two constructors that are very similar. It's reasonable to suspect that constructing with 'true' is hitting the first one. Try removing that constructor for a sec and see what you get.

            BooleanArray(int intLength);
            BooleanArray(boolean booleanValue);

You may want to use the built-in type 'bool' rather than the defined type 'boolean' which is equivalent to 'unsigned char'. The bool type is constrained to values of 0 and 1 (although on the Arduino it still uses 8 bits of storage).

Here's a tip ... add debugging code, like this:

BooleanArray::BooleanArray()
{
  Serial.println (__PRETTY_FUNCTION__);
  arrayLength = 0;
  arrayPointer = (boolean *)calloc(1,sizeof(boolean));
}

I put the "PRETTY_FUNCTION" print at the start of every constructor. Now running your code:

BooleanArray::BooleanArray(boolean)
void BooleanArray::set(int, boolean)
String BooleanArray::toString()
String BooleanArray::toString(int, int)
boolean BooleanArray::get(int)
{true}
BooleanArray::BooleanArray(int)
void BooleanArray::set(int, boolean)
String BooleanArray::toString()
String BooleanArray::toString(int, int)
boolean BooleanArray::get(int)
{false}

You can see that the second constructor call is not the one you thought you were getting. You got this one:

BooleanArray::BooleanArray(int intLength)

And if you look in Wiring.h you find:

typedef uint8_t boolean;
typedef uint8_t byte;

So really boolean is just like a byte, not a bool (as johnwasser said).

Even if you change-all "boolean" to "bool" it still gives the same results? Why? Because of this:

#define true 0x1
#define false 0x0

Note that "true" is not defined as boolean type. It is just an int. And thus you get the "int" constructor, not the boolean one.

For me there is too much confusion and duplication in this code.

And you know what? You have a lot of code there that is basically implementing what amounts to the STL "vector" class. Your code as posted compiles to 5164 bytes. Compare to this (in its entirety):

#include <iterator>
#include <vector>
#include <new.cpp>

using namespace std;

void printVector (const vector<bool> & v)
{
  vector<bool>::const_iterator it;
  for (it = v.begin (); it != v.end (); it++)
    Serial.println (*it ? "true" : "false");
}  // end of printVector

void setup(){

  Serial.begin(115200);
  
  vector<bool> array1 (5);  // 5 elements
  
  bool B = true;
  array1 [0] = B;
  printVector (array1);
    
  vector<bool> array2;   // 0 elements
  array2.push_back (true);  // add an element
  printVector (array2);
  
  bool C = array2 [0];  // get an element back
  Serial.print ("C = ");
  Serial.println (C);  
}  // end of setup

void loop(){}

The STL version above compiles in 3688 bytes, that's a lot less.

Output:

true
false
false
false
false
true
C = 1

The STL library handles it all (except the printing). Adding, removing, resizing, memory allocation. And you can use vectors of int, byte, whatever you want.

My notes for how to access that library here:

STL port by Andrew Brown.