function parameter types

Wrote this little sketch to peek at bits in a variable, it's called like:
prntBits(8,PIND);

void prntBits(int numBits, uint32_t val)
{
  for(numBits -= 1;numBits >= 0;numBits--)
  {
    Serial.print(bitRead(val,numBits));
    if(numBits % 4 == 0) Serial.print(" ");
    if(numBits % 8 == 0) Serial.print(" ");
  }  
  Serial.println();  
}

I made the size of "val" uint32_t so it would take any integer size (besides long long), is there a way to make val accept any integer size so I could calculate "numBits" from "sizeof(val) * 8"? I tried "size_t val" but no workum.
Here's a working sketch:

void setup()
{
  Serial.begin(9600);
}
void loop()
{
  int adc = analogRead(A0);
  prntBits(10,adc);
  delay(1000);
}

void prntBits(int numBits, uint32_t val)
{
  for(numBits -= 1;numBits >= 0;numBits--)
  {
    Serial.print(bitRead(val,numBits));
    if(numBits % 4 == 0) Serial.print(" ");
    if(numBits % 8 == 0) Serial.print(" ");
  }  
  Serial.println();  
}

the compiler will allocate the number of bytes that are necessary for the type of variable you declare. so here you said it's a 32 bit unsigned integral and thus in the function you will always see 4 bytes, regardless if you called the function by passing a uint16_t or uint8_t or uint32_t. The compiler will have automatically cast before the call that value into a uint32_t.

What you could check is if the most significant bytes are empty, and second guess what's really necessary to print out

The other option is to use the fact that you can have multiple functions with the same name if the parameters are different (it's called the signature of the function). for example if you run this

void f1(uint8_t v8)
{
  Serial.println("8 bits");
}

void f1(uint16_t v16)
{
  Serial.println("16 bits");
}

void f1(uint32_t v32)
{
  Serial.println("32 bits");
}

void setup() {
  uint8_t a8 = 100;
  uint16_t a16 = 100;
  uint32_t a32 = 100;
  Serial.begin(115200);
  f1(a8);
  f1(a16);
  f1(a32);
}

void loop() {}

Uou'll see in the console

[sub][color=blue]8 bits
16 bits
32 bits
[/color][/sub]

so to your programming needs you only need to remember the f1() function but in real code, based on the type you pass in parameter, different code is being called.

is there a way to make val accept any integer size so I could calculate "numBits" from "sizeof(val) * 8"?

Can you do the calculation of the number of bits as part of the function call ?

  int x = 123;
  prntBits(sizeof(x) * 8, x);
  unsigned long y = 12345;
  prntBits(sizeof(y) * 8, y);

Note that the prntBits() function will not work with a byte variable.

outsider:
I made the size of "val" uint32_t so it would take any integer size (besides long long), is there a way to make val accept any integer size so I could calculate "numBits" from "sizeof(val) * 8"? I tried "size_t val" but no workum.

if you use a template you don't need to pass the size:

template <class T> void printBits(T &value)
{
  Serial.print(F("0b"));
  for (size_t i = 0; i < sizeof(T) * 8; i++)
  { 
    T mask = 1;
    Serial.print((value & (mask << sizeof(value) * 8-i-1)) ? "1" : "0");
  }
  Serial.println();
};

void setup() 
{
  Serial.begin(9600);
  uint8_t num = 0xF0;
  uint64_t val = 0xFF00FF00FF00FF00;
  printBits(num);
  printBits(val);
}

void loop() 
{

}

** this example won't work for floats :frowning:

Alright guys, got something to work, kind of klunky and could do with some refinement, (how to put all in 1 "box"?) but works so far, (acid testing now).
TNX all and K++ all around for helpful suggestions.

void prntBits(char val)
{
  showBits(sizeof(val) * 8,val);
}
void prntBits(uint8_t val)
{
  showBits(sizeof(val) * 8,val);
}
void prntBits(int16_t val)
{
  showBits(sizeof(val) * 8,val);  
}
void prntBits(uint16_t val)
{
  showBits(sizeof(val) * 8,val);
}
void prntBits(int32_t val)
{
  showBits(sizeof(val) * 8,val);
}
void prntBits(uint32_t val)
{
  showBits(sizeof(val) * 8,val);
}

void showBits(int nrBits, uint32_t value)
{
    for(nrBits -= 1;nrBits >= 0;nrBits--)
  {
    Serial.print(bitRead(value,nrBits));
    if(nrBits % 4 == 0) Serial.print(" ");
    if(nrBits % 8 == 0) Serial.print(" ");
  }  
  Serial.println();
}

@bulldogL:
I'm intrigued by your template sketch, but I get:

Arduino: 1.6.5 (Linux), Board: "Arduino Pro or Pro Mini, ATmega328 (5V, 16 MHz)"

Build options changed, rebuilding all
sketch_dec22d:2: error: variable or field 'printBits' declared void
sketch_dec22d:2: error: 'T' was not declared in this scope
sketch_dec22d:2: error: 'value' was not declared in this scope
variable or field 'printBits' declared void

  This report would have more information with
  "Show verbose output during compilation"
  enabled in File > Preferences.

Templates and classes are still over the Moon for me. :slight_smile: Do you want to see the verbose version?

If you update to Arduino IDE 1.8.5 the template sketch will work. If you want to stick with 1.6.5 you'll need to move the template to a .h file.

Tnx, I'll get 1.8.5 soon and try.

@BulldogLowell:
Amazing! A keeper, now if I can figure out how it works. :confused:
Many TNX and a K++.

Templates are a really amazing feature of C++. They can make code really confusing but they sure are useful at times.