Go Down

Topic: Multiple of value type vs array (Read 984 times) previous topic - next topic

fuzzball27

In Arduino, do multiples of the same value type take up more bits than an array with same number of that value type?

In other words:

Code: [Select]

//Does this
byte a = x;
byte b = y;
byte c = z;

//Take up the same number of bits as this?
byte letter[3] = {x, y , z};



Or does the answer vary based on the value type?

So:

Code: [Select]

//Maybe this
byte a = x;
byte b = y;
byte c = z;

//Takes up fewer bits than this
byte letter[3] = {x, y, z};

//But this
long a = x;
long b = y;
long c = z;

//Takes up more bits than this?
long letter[3] = {x, y, z};
fuzzball27 >>-->

marco_c

Any single data type takes the space it takes and multiples take a multiple of that, no matter how they are declared (single or array). So three individual longs take up the same space as an array of long of size 3.

Arrays are a matter of convenience. if I have 256 values, then declaring 256 and referencing variables is a pain, plus you can't use loops to manipulate the data. Arrays are much better in that situation.
Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

WizenedEE

Code: [Select]

int v1;
int v2;
int v3;
int v4;
int v5;
int v6;
int v7;
int v8;

v1 = 3;
v2 = 4;
v3 = 5;
v4 = 6;
v5 = 7;
v6 = 8;
v7 = 9;
v8 = 10;

Takes up more space than
Code: [Select]

int v[8];
for (int i=0; i<8; i++) {
  v[i] = i+3;
}

Esepcially with large arrays

fuzzball27

Ok thanks. That's what I figured, but I had some hope that there might be a technique similar to packing several true/false values into a single byte.
fuzzball27 >>-->

Tom Carpenter

#4
Jul 21, 2012, 07:59 pm Last Edit: Jul 21, 2012, 08:03 pm by TCWORLD Reason: 1
You can use bytes to store 8 bits (flags).

E.g.

Code: [Select]
byte flag = 0; //No bits set
flag |= _BV(1); //Set bit 1.

if (flag & _BV(1)){
  //If bit one is true
  flag &= ~_BV(1); //Maybe clear it again
  flag |= (_BV(2)  | _BV(3)); //Set bits 2 and 3.
}
if (flag & (_BV(2) | _BV(3))){
  //If bits 2 and 3 are set
  flag &= ~_BV(2); //Maybe clear bit 2
}

if (!(flag & _BV(2)) && (flag | _BV(3))){
  //If bit 3 is set, and bit 2 isn't
 
}



and so on
~Tom~

GoForSmoke


Code: [Select]

int v1;
int v2;
int v3;
int v4;
int v5;
int v6;
int v7;
int v8;

v1 = 3;
v2 = 4;
v3 = 5;
v4 = 6;
v5 = 7;
v6 = 8;
v7 = 9;
v8 = 10;

Takes up more space than
Code: [Select]

int v[8];
for (int i=0; i<8; i++) {
  v[i] = i+3;
}

Esepcially with large arrays


I guess it depends on what you mean by "more space". 
Do you think it makes any difference to space taken in SRAM?
I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

marco_c

Quote
I had some hope that there might be a technique similar to packing several true/false values into a single byte


There are for quantities that are less than one byte or word (like the bit flags you are referring to). For example, if you know that a certain value will never exceed 15 (4 bits) then you can pack 2 of those in the hi and low nybble of a byte. Or if a value is 0-7 (3 bits) then 5 can fit in a 16 bit word, etc. This is not automatic, though, and you will need to manage the storage, saving and retrieving through your own code.

It comes down to a tradeoff between execution speed and RAM - if there is enough data that the added complexity would save lots of memory, then it makes sense. Otherwise, for me, ease of understanding (now and in future, when I come back to look at the code) is a higher priority than saving a few bytes.
Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

GoForSmoke

You can use a struct or union with bitfields to clean up such code.

here's a nice explanation:
http://cplus.about.com/od/learningc/ss/lowlevel_10.htm

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

pYro_65

BitFields are useful for interpreting irregular data but when used for declaring types they suffer. The elements of a bit field are non-addressable unlike standard struct members. Also due to their definition being implementation defined they are not portable.

I wrote a class not to long ago to create a bit sized boolean style array, I have not completed the hardware that I intended it for so it still remains untested. It allows reading and writing of elements just like an array, also it uses the smallest possible data types for the number of elements ( uint8_t for 256 elements or less, uint32_t for 4294967295 elements ).



BitBool.h
Code: [Select]
#if defined(ARDUINO) && ARDUINO >= 100
 #include <Arduino.h>
#else
 #include <WProgram.h>
#endif    

template< uint32_t _Items > class BitBool{
 protected:
   template< bool _Flag, typename _True, typename _False > struct If{ typedef _True Result; };
   template< typename _True, typename _False >             struct If< false, _True, _False >{ typedef _False Result; };
   template< uint32_t _A, uint32_t _B >                    struct IsGreaterThan{ static const bool Value = _A > _B; };
   typedef typename If< IsGreaterThan< _Items, 0x100 >::Value, typename If< IsGreaterThan< _Items, 0x10000 >::Value, uint32_t, uint16_t >::Result, uint8_t >::Result INDEX_TYPE;
 private:
   class TemporaryObj{
     public:
       TemporaryObj( const uint8_t u_Idx, uint8_t * const u_Ptr ) : u_Index( u_Idx ), u_Data( u_Ptr ) { return; }
       operator const bool( void ){ return *this->u_Data & ( 1 << this->u_Index ); }
       const bool operator =( const bool b_NewValue )
         {
           if( b_NewValue )  *this->u_Data &= ~( 1 << this->u_Index );
           else              *this->u_Data |= ( 1 << this->u_Index );
           return            b_NewValue;
         }
     protected:
     private:
       const uint8_t    u_Index;
       uint8_t * const  u_Data;            
   };
 public:
   TemporaryObj operator[]( const INDEX_TYPE i_Pos ){ return TemporaryObj( i_Pos & 7, this->u_Data + ( i_Pos >> 3 ) ); }
   uint8_t u_Data[ ( _Items / 8 ) + ( ( ( _Items % 8 ) > 0 ) ? 1 : 0 ) ];        
};
template<> struct BitBool< 0 >{ bool operator[]( const int ){ return false; } };


Sketch
Code: [Select]
#include "BitBool.h"

//32 elements
BitBool< 32 > b_Data = { 0xFF, 0x00, 0xFF, 0x00 }; //Can preset values.

//75 elements
BitBool< 75 > b_Data1;

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

void loop( void )
 {
   static bool b = false;
   
   if( b = !b ) for( int k = 0 ; k< 512 ; ++k) b_Data[ analogRead( A0 ) ] = analogRead( A1 ) > 512;
   else         for( int k = 0 ; k< 512 ; ++k) Serial.println( b_Data[ k ] ? "True" : "False" );
   return;
 }


Take note the code compiles but is untested.

Go Up