Hi all

Happy to join this forum, hope you can help me from time to time :)
I'm and electrical engineer, and I use C program as part of my work,
at a very basic level, just to control a piece of hardware.

I now have a problem which I'm sure is very basic..for you..
I have an array of unsigned char elements, which are actually hex numbers.
Something like :
unsigned char data[BYTES]={0x3f,0x20,0xf2};

When I try to print this array with :
for(j=0;j<BYTES;j++) printf("%02X\n",data[j]);

I get :
3F
20
FFFFFFF2

Any hex number who has '1' in the msb prints with 6 'F' in the beginning.
I guess it has to do with 1 or 2's complement.
How can I get the print to be always 2 digits ?

Thanks !

I just tried your code on a AMD/64

#include <stdio.h>

unsigned char data[3] = {0x3f,0x20,0xf2};


int main()
{
	int j = 0;
	for(j=0;j<3;j++) 
		printf("0x%x\n",data[j]);

	return 0;
}

And it produced output

0x3f
0x20
0xf2

Edited 6 Years Ago by gerard4143: n/a

weird, I just tried it again with larger array, same result :
BTW - I'm running on unix, SunOS4.1 (very old machine..)

unsigned char data[28]=
{0xF0,0xE0,0xD0,0xC0,0xB0,0xA0,0x90,0x80,0x70,0x60,0x50,0x40,0x30,0x20,0x10,0x00,0xff,0x2f,0x1f,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01};


for (j=0; j<28; j++) printf("[%02x]\n", data[j]);

[fffffff0]
[ffffffe0]
[ffffffd0]
[ffffffc0]
[ffffffb0]
[ffffffa0]
[ffffff90]
[ffffff80]
[70]
[60]
[50]
[40]
[30]
[20]
[10]
[00]
[ffffffff]
[2f]
[1f]
[09]
[08]
[07]
[06]
[05]
[04]
[03]
[02]
[01]

Edited 6 Years Ago by karpe: n/a

I love programming for electronics. Its like watching your programs come to life, literally!

printf() is an awesome function, and its strange to see such code not behave properly.

Here is an idea which might work in your specific implementation. Basically I use snprintf() to do the work of converting the hex, but force it into a 3 character temporary space, and once its crammed in there, you print that.

unsigned char 
  data[BYTES] = {0x3f,0x20,0xf2},
  temp[]      = {0x0, 0x0, 0x0};
for(j=0; j<BYTES; j++) {
  snprintf(temp, 3, "%02x", data[j]);
  printf("%s\n", temp);
}

An alternative logic if that fails is to provide enough space in temp[] for the entire erroneous code, then only copy the two characters you need. But try that method first and see if it works.

Edited 6 Years Ago by N1GHTS: n/a

Hi

Thanks, I know how to workaround this by truncating the string, but I want
the elegant solution + understanding of the problem..

Thanks !

The problem is probably the compiler. What compiler do you use and on what platform?

By the way, in my opinion, an elegant solution is one with the least clock cycles, weather it be ugly or not. And if you want that kind of solution, i'd suggest converting the bytes to hex yourself since the printf() family of functions are not cycle friendly.

it's not a real-time program so I don't care about clock cycles.
I work on Sun sparc station, SunOS4.1.
The compiler is called 'lcc'.

I have a new finding - I have a function which I copied from external source.
this function gets a pointer to that same array, and if I do the same print
from within the function it prints ok.

The function gets const unsigned char *, and I'm doing cast to the pointer
to avoid the compiler warning.
I tried the same case inside the printf, but no difference..

I'm not completely sure what could exactly be wrong but just to let you know why I think it prints all those F's is because numbers past 127 will be considered negative numbers, therefore: 0x0 - 0x1 = 0xFFFFFFFF. But since you not only specified "unsigned", but also specified "%02", it leads me to think that there may be a bug with the library or compiler itself, and that is always a possibility, especially on non main-stream compilers.

OK, some progress..I think.
I created a small function that all it does it get the pointer
to the array and it's length and print it the same way :

void print_array(const unsigned char* data, int length) 
{

int j;
printf("Printing array :\n");
for (j=0; j<length; j++) printf("#%02X#\n", data[j]);
printf("\n");

}

This outputs ok :

Printing array :
#F0#
#E0#
#D0#
#C0#
#B0#
#A0#
#90#
#80#
#70#
#60#
#50#
#40#
#30#
#20#
#10#
#00#
#FF#
#2F#
#1F#
#09#
#08#
#07#
#06#
#05#
#04#
#03#
#02#
#01#

Now, just before calling this function I printed the same array directly,
with same problem :

for (j=0; j<BYTES; j++) printf("[%02X]\n", (const unsigned char *) data[j]);
print_array((const unsigned char *) data,BYTES);
[FFFFFFF0]
[FFFFFFE0]
[FFFFFFD0]
[FFFFFFC0]
[FFFFFFB0]
[FFFFFFA0]
[FFFFFF90]
[FFFFFF80]
[70]
[60]
[50]
[40]
[30]
[20]
[10]
[00]
[FFFFFFFF]
[2F]
[1F]
[09]
[08]
[07]
[06]
[05]
[04]
[03]
[02]
[01]

Have you tried without using brackets? Maybe the brackets are interfering? Try the pound signs like in the first version.

still the same ...

#FFFFFFF0#
#FFFFFFE0#
#FFFFFFD0#
#FFFFFFC0#
#FFFFFFB0#
#FFFFFFA0#
#FFFFFF90#
#FFFFFF80#
#70#
#60#
#50#
#40#
#30#
#20#
#10#
#00#
#FFFFFFFF#
#2F#
#1F#
#09#
#08#
#07#
#06#
#05#
#04#
#03#
#02#
#01#

In your code the following cast is wrong

for (j=0; j<BYTES; j++) printf("[%02X]\n", (const unsigned char *) data[j]);

Could you post the complete compilable code which demonstrates the working and non-working behaviour. I think your problem eventually relates to the default char being signed.

Edited 6 Years Ago by mitrmkar: n/a

problem solved, you are right, I got help from a friend who found the bug.

The array was declared in a different c file, indeed as unsigned char.
But in the problematic c file it was defined as 'extern char', after
changing it to 'extern unsigned char' it's working ok.
The reason that it worked by using the function is that the call to the function
made the casting.

Thanks all for your help !

problem solved, you are right, I got help from a friend who found the bug.

The array was declared in a different c file, indeed as unsigned char.
But in the problematic c file it was defined as 'extern char', after
changing it to 'extern unsigned char' it's working ok.
The reason that it worked by using the function is that the call to the function
made the casting.

Thanks all for your help !

This article has been dead for over six months. Start a new discussion instead.