Increment by one and hex result

Hi guys,

Does anyone can help on this:

I need to increment by one an int variable from 0 to 8000 and get the result in hex values lo and hi bytes like this:

If the variable value == 0001 I need a result == 0x00 0x01 4000 == 0x0F 0xA0 8000 == 0x1F 0x40

Please...

Thanks in advance

char text[11];
  for (int number=0; number<=8000; number++) {
    Serial.print(number);
    sprintf(text, " 0x%02X 0x%02X", (byte)(number>>8), number&0xFF);
    Serial.println(text);
  }

Whandall gave you a nice crisp solution, but here’s an alternative if you run into memory issues:

union {
  unsigned char pieces[2];
  int val;
} myUnion;

void setup() {
  char pad[5];

  Serial.begin(9600);
  
  for (int number=00; number<=8000; number++) {
    Serial.print(number);
    Serial.print("   ");
    myUnion.val = number;                // Move value into union
    DoPad(myUnion.pieces[1], pad); 
    Serial.print(pad);
    Serial.print( (unsigned char) myUnion.pieces[1], HEX);  // Extract the pieces of val from union
    DoPad(myUnion.pieces[0], pad); 
    Serial.print("   ");
    Serial.print(pad);    
    Serial.println((unsigned char)  myUnion.pieces[0], HEX);    
  }
}

void DoPad(unsigned char val, char *spaces)
{
  if (val < 16)
    strcpy(spaces, "0x0");
  else
    strcpy(spaces, "0x");
}

void loop() {
}

Whandall’s code uses 3730 bytes of memory while the code above uses 2420 bytes. Even though there are more lines of code in the program above, its code size is smaller because sprintf() is a pretty large function with lots of features, most of which go unused in most programs. If you ever start to bump into program space problems and the code uses sprintf(), see if you can factor it out using alternative code.

I think my version is less difficult to explain to the teacher.

;)

Whandall:     sprintf(text, " 0x%02X 0x%02X", (byte)(number>>8), number&0xFF);

I prefer (number>>8)&0xFF to keep it consistent with the other expression, and because after you cast it to byte it's only going to get promoted back to int again. Pretty sure it won't get sign-extended (because byte is unsigned), but still … .

econjack: union {   unsigned char pieces[2];   int val; } myUnion;

Works if you are sure about the endian-ness of the machine it runs on, and that int is 2 bytes. For embedded systems when you are writing for a particular chip, is ok. BUt it's a thing to be aware of.

Whandall: I think my version is less difficult to explain to the teacher.

Always an issue, sadly.

for (int number=0; number<=8000; number++) {
    int temp = number>>8;
    const char Hex[] = "0x";
    
    Serial.print(Hex);
    if(temp <= 0xF){
      Serial.print('0');
    }
    Serial.print(temp, HEX);
    
    Serial.print(' ');
    Serial.print(Hex);
    temp = number&0xFF;
    if(temp <= 0xF){
      Serial.print('0');
    }
    Serial.println(temp, HEX);
  }

2360 bytes, easy to explain :stuck_out_tongue:

Although I saved 6 bytes with the const char Hex I would do it just inline…

And if we go for space, theres one more version

void nibble(char* store, byte iIn) {
  iIn &= 0xF;
  *store = iIn<10?'0'+iIn:'A'-10+iIn;
}

void printStuff() {
char text[11] = " 0x-- 0x--";
char numBuff[7];
int work;
  for (int number=0; number<=8000; number++) {
    work = number;
    nibble(&text[9], work);
    work >>= 4;
    nibble(&text[8], work);
    work >>= 4;
    nibble(&text[4], work);
    work >>= 4;
    nibble(&text[3], work);
    itoa(number, numBuff, 10);
    Serial.print(numBuff);
    Serial.println(text);
  }
}

2.098 Bytes :wink:

Endianess is an issue for code like this. I could have helped with more portable code:

union {
  unsigned char pieces[sizeof(int)];
  int val;
} myUnion;

and there are way to test for the byte order (e.g., see http://www.xappsoftware.com/wordpress/2010/12/12/the-endianness-problem-and-how-to-test-the-endianness/). Still, most of us are writing for a specific processor and I would think we can guess the proper sequence after one run of the program. Finally, my real purpose was to point out the overhead associated with sprintf() and that alternatives exist to add a different tool onto your tool belt. After all, if the only tool you have is a hammer, all of your problems end up looking like a nail.

Here is how I would do it

struct
{
  union
  {
    struct
    {
      uint8_t
        nibble0 : 4,
        nibble1 : 4
      ;
    } bytes[2];
    uint16_t val;
  };
} myVal;

void printStuff()
{
  char hexPrefix[3] = "0x";

  for ( myVal.val = 0; myVal.val <= 8000; myVal.val ++ )
  {
    Serial.print( hexPrefix );
    Serial.print( hexChar( myVal.bytes[1].nibble1 ) );
    Serial.print( hexChar( myVal.bytes[1].nibble0 ) );

    Serial.print( ' ' );

    Serial.print( hexPrefix );
    Serial.print( hexChar( myVal.bytes[0].nibble1 ) );
    Serial.print( hexChar( myVal.bytes[0].nibble0 ) );

    Serial.print( '\n' );
  }
}

char hexChar( const uint8_t nibble )
{
  return nibble + ( nibble < 0xA ? '0' : 'A' - 0xA );
}