3

I have done the reading from a file and is stored as hex values(say the first value be D4 C3). This is then stored to a buffer of char datatype. But whenever i print the buffer i am getting a value likebuff[0]=ffffffD4; buff[1]=ffffffC3 and so on. How can I store the actual value to the buffer without any added bytes? Attaching the snippet along with this

ic= (char *)malloc(1);
temp = ic;  
int i=0;
char buff[1000];

while ((c = fgetc(pFile)) != EOF) 
{
  printf("%x",c);
  ic++;        
  buff[i]=c;
  i++;
}
printf("\n\nNo. of bytes written: %d", i);
ic = temp;
int k;
printf("\nBuffer value is :   ");
for(k=0;k<i;k++)
{
  printf("%x",buff[k]);
}
Andreas Fester
  • 36,091
  • 7
  • 95
  • 123
Parvathi
  • 97
  • 2
  • 8
  • I see two potential (but unrelated) problems: First [don't cast the return of `malloc` (and friends)](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-mallo‌​c) (or any function returning `void *`) in C. Second, is the variable c and int or a char? Remember that [`fgetc`](http://en.cppreference.com/w/c/io/fgetc) return an `int`. There are also a lot of variables that you don't really use anywhere, like `ic`, you never really do anything with it? – Some programmer dude Dec 04 '15 at 07:18
  • 1
    Then your code won't work as expected, because `(char) EOF != (int) EOF` – Some programmer dude Dec 04 '15 at 07:26
  • Thanks alot with ur time.. it is solved now. The issue was with the wrong datatype declaration – Parvathi Dec 04 '15 at 07:26

3 Answers3

5

The problem is a combination of two things:

  • First is that when you pass a smaller type to a variable argument function like printf it's converted to an int, which might include sign extension.
  • The second is that the format "%x" you are using expects the corresponding argument to be an unsigned int and treat it as such

If you want to print a hexadecimal character, then use the prefix hh, as in "%hhx".

See e.g. this printf (and family) reference for more information.

Finally, if you only want to treat the data you read as binary data, then you should consider using int8_t (or possibly uint8_t) for the buffer. On any platform with 8-bit char they are the same, but gives more information to the reader of the code (saying "this is binary data and not a string").

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Using `hh` isn't portable enough. Despite it's in standard since C99, Microsoft doesn't support it (according to the today MSDN version). – Netch Dec 04 '15 at 07:38
  • @Netch Only partially true, VS2015 [includes a fully conformant C99 standard library](https://msdn.microsoft.com/en-us/library/hh409293.aspx) (except features depending on missing compiler features, the `printf` formatting string should not be such a depending feature). If it's *really* implemented or it's the MSDN pages that haven't been properly updated I don't know. – Some programmer dude Dec 04 '15 at 07:44
1

You did store the actual values in the buffer without the added bytes. You're just outputting the signed numbers with more digits. It's like you have "-1" in your buffer but you're outputting it as "-01". The value is the same, it's just you're choosing to sign extend it in the output code.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
1

By default, char is signed on many platforms (standards doesn't dictate its signedness). When passing to variable argument list, standard expansions like char -> int are invoked. If char is unsigned, 0xd3 remains integer 0xd3. If char is signed, 0xd3 becomes 0xffffffd3 (for 32-bit integer) because this is the same integer value -45.

NB if you weren't aware of this, you should recheck the entire program, because such errors are very subtle. I've dealed once with a tool which properly worked only with forced -funsigned-char into make's CFLAGS. OTOH this flag, if available to you, could be a quick-and-dirty solution to this issue (but I suggest avoiding it for any longer appoaching).

The approach I'm constantly using is passing to printf()-like functions a value not c, but 0xff & c, it's visually easy to understand and stable for multiple versions. You can consider using hh modifier (UPD: as @JoachimPileborg have already suggested) but I'm unsure it's supported in all real C flavors, including MS and embedded ones. (MSDN doesn't list it at all.)

Netch
  • 4,171
  • 1
  • 19
  • 31