printf char as hex in c - c

I expect ouput something like \9b\d9\c0... from code below, but I'm getting \ffffff9b\ffffffd9\ffffffc0\ffffff9d\53\ffffffa9\fffffff4\49\ffffffb0\ffff
ffef\ffffffd9\ffffffaa\61\fffffff7\54\fffffffb. I added explicit casting to char, but it has no effect. What's going on here?
typdef struct PT {
// ... omitted
char GUID[16];
} PT;
PT *pt;
// ... omitted
int i;
for(i=0;i<16;i++) {
printf("\\%02x", (char) pt->GUID[i]);
}
Edit: only casting to (unsigned char) worked for me. Compiler spits warnings on me when using %02hhx (gcc -Wall). (unsigned int) had no effect.

The reason why this is happening is that chars on your system are signed. When you pass them to functions with variable number of arguments, such as printf (outside of fixed-argument portion of the signature) chars get converted to int, and they get sign-extended in the process.
To fix this, cast the value to unsigned char:
printf("\\%02hhx", (unsigned char) pt->GUID[i]);
Demo.

Use:
printf("\%02hhx", pt->GUID[i]);
Because printf() is a variadic function, its arguments are promoted to int. The hh modifier tells printf() that the type of the corresponding value is unsigned char and not int.

Cast to unsigned char instead, to avoid a leading 1 bit being interpreted as a negative value.

I noticed that you were getting the F's when the number was larger than 99x.
I wrote this to test it out and discovered the hh prefix at http://www.cplusplus.com/reference/cstdio/printf/
#include "stdio.h"
char GUID[16];
int main() {
int i;
for(i=0;i<16;i++) {
GUID[i]=i*i;
}
for(i=0;i<16;i++) {
printf("\\%02.2hhx\n", GUID[i]);
}
return 0;
}

Use a small own implementation to solve this problem on all platforms:
char hex[] = "0123456789abcdef";
void printHex(unsigned char byte) {
printf("%c%c", hex[byte>>4], hex[byte&0xf]);
}

Related

assign zero in unsigned short int in c

I try to assign zero to a field in a structure called list
list.ultimo = 0;
but when I use printf
printf("%d", list.ultimo);
I get the result
32766
but when I add
unsigned short int cero = 0;
the result of printf is correct, no matter that does not use cero. why?
lista.h
#ifndef LISTA_H
#define LISTA_H
typedef struct{
elemento lista[TAMANOMAX];
unsigned short int ultimo;
}LISTA;
void Insertar(elemento, unsigned short int posicion, LISTA);
#endif
lista.c
#include<stdio.h>
typedef short int elemento;
#ifndef TAMANOMAX
#define TAMANOMAX 10
#endif
#include"lista.h"
void Insertar(elemento x, unsigned short int p, LISTA lista){
if (lista.ultimo >= TAMANOMAX){
puts("full list");
printf("%hu",lista.ultimo);
}
}
main.c
#include<stdio.h>
typedef unsigned short int elemento;
#define TAMANOMAX 4
#include"lista.h"
int main(){
LISTA esferas;
esferas.ultimo = 0;
Insertar(2,0,esferas);
printf("\n%hu\n", esferas.ultimo);
return 0;
}
the result is
$gcc -Wall lista.c main.c
full list
32765
0
I'm new to this, I'm slow for now, I regret the delay
Use %hd to print a short int and %hu to print an unsigned short int. %d is for int.
EDIT: Now that you have posted the full code, it appears that TAMANOMAX is set to 10 in lista.c, but set to 4 in main.c, leading to an incompatibilty between your main() function and the Insertar one. You should have the same value in all files. And if you want to work with different array lengths, add a length member in your LISTA structure. But TAMANOMAX should absolutely be the same everywhere, else you're in fact working with different data types and your program won't work.
Using mismatched format specifier with the type of the argument invokes undefined behavior.
Quoting C11 standard, chapter ยง7.21.6.1, fprintf() function
[..] If any argument is
not the correct type for the corresponding conversion specification, the behavior is
undefined.
and about %d format specifier,
d,i The int argument [....]
so, %d expects an int.
As per your question title, ultimo is unsigned short int and you're using %d to print the value.
You should use %hu to print unsigned short int.

Why won't this C program print the unsigned int?

I wrote this function to reverse a number. I will have test cases that are up to 2^32. I need the function to return unsigned ints. My question is this: why wont this print?
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
unsigned int reverse(unsigned int a);
int main(){
printf("%u\n",reverse(987654321));
//printf("%ui\n",reverse(987654321)); //this wont work either
return 0;
}
unsigned int reverse(unsigned int a)
{
int temp=0;
while(a>0)
{
temp=10*temp+a%10;
a/=10;
}
return temp;
}
Yes I did forget about the proto-type... Bear with me I have been doing Java and Lisp lately. However, my compiler keeps giving me a warning saying I have extra characters in the format string. It also does this if I have type "long long int" and I use "%lli% in the format string, which I also tried.
You forgot to include prototype for your function before main.
unsigned int reverse(unsigned int a);
The number probably is just too big for an unsigned on your architecture.
Remember to always enable maximum warning level for your compiler. This should have told you that reverse is not known where you use it, that you are passing an int to the %u format and also that your number ist too big.

Function working fine in stand alone mode but not in a larger program

I have a c program with multiple headers and source files. On running, the program gives segmentation fault. On using "up" and "print variable" commands, i figured that the function "busntoint()" is not working properly.
I have following functions for converting a string of length n from binary to decimal:
unsigned int busntoint(int n, busn bus)
{
unsigned int value = 0;
int i;
for (i=0; i < n; i++) {
if (bus[i] == '1') value += (unsigned int)pow(2,(n-1-i));
}
return value;
}
unsigned int bus2toint(bus2 bus)
{
return busntoint(2, bus);
}
unsigned int bus32toint(bus32 bus)
{
return busntoint(32, bus);
}
I then wrote another program to check the working of these functions. It works just fine and gives the correct and expected output. I dunno why it is not working properly in the "bigger" program.
If it's useful, following is the definition of variables:
typedef char bus2[3];
typedef char bus3[4];
typedef char bus5[6];
typedef char bus6[7];
typedef char bus8[9];
typedef char bus16[17];
typedef char bus32[33];
The usage of the function in the "bigger" program is as follows:
int LoadMemory(char * binfilename, bus8 memory[4096])
{
//some code
int addr = bus32toint(line);
setbit8(memory[addr], &line[33]);
//some code
}
p addr in gdb gives garbage value, leading to segmentation fault in memory[addr].
Your first problem probably lies in your abuse of pow to compute powers of two and the possible overflow that your computation may encounter.
The correct way of computing integer powers of two is the shift operator, here that would be
2u << (n-1-i)
the suffix u is to ensure that this has the correct type (unsigned). But then you also have to ensure that the value by which you are shifting is not too large, you must guarantee that the corresponding power will still fit into an unsigned. You didn't tell us on what architecture your are, not all have unsigned with 32 bit.
Then your LoadMemory function also looks bogus. As far as I can see there can no guarantee be given that addr (for which you didn't show the type) is smaller than 4096.
Use unsigned int addr = bus32toint(line);

Printf raw data to a fixed length hex output

I have a struct, well pointer to a struct, and I wish to printf the first n bytes as a long hex number, or as a string of hex bytes.
Essentially I need the printf equivalent of gdb's examine memory command, x/nxb .
If possible I would like to still use printf as the program's logger function just variant of it. Even better if I can do so without looping through the data.
Just took Eric Postpischil's advice and cooked up the following :
struct mystruc
{
int a;
char b;
float c;
};
int main(int argc, char** argv)
{
struct mystruc structVar={5,'a',3.9};
struct mystruc* strucPtr=&structVar;
unsigned char* charPtr=(unsigned char*)strucPtr;
int i;
printf("structure size : %zu bytes\n",sizeof(struct mystruc));
for(i=0;i<sizeof(struct mystruc);i++)
printf("%02x ",charPtr[i]);
return 0;
}
It will print the bytes as fas as the structure stretches.
Update : Thanks for the insight Eric :) I have updated the code.
Try this. Say you have pointer to struct in pstruct.
unsigned long long *aslong = (unsigned long long *)pstruct;
printf("%08x%08x%08x%08x%08x%08x%08x%08x",
aslong[0],
aslong[1],
aslong[2],
aslong[3],
aslong[4],
aslong[5],
aslong[6],
aslong[7],
);
As Eric points out, this might print the bytes out-of-order. So it's either this, or using unsigned char * and (having a printf with 64 arguments or using a loop).

c printf size_t

My code compiles, though the printf doesn't display anything?
If I take out the formatter part of the printf then it works just fine.
#include <stdio.h>
size_t MyStrlen(const char *s1)
{
const char *s1Copy = s1;
while (*s1)
{
*s1Copy++;
}
return s1Copy -s1;
}
int main(void)
{
const char str[] = "HELLO";
printf("Length: %d \n", (unsigned int)MyStrlen(str));
return 0;
}
In your loop test you want to test *s1Copy for non-NULL, not *s1, which you aren't incrementing. As it is, since *s1 never changes, you're walking right off the end of your string argument with s1Copy++ and the code won't terminate normally.
Unless of course you pass the empty string: your MyStrlen method will work for the empty string.
while (*s1Copy)
s1Copy++;
This:
printf("Length: %d \n", (unsigned int)MyStrlen(str));
is ok; %d expects an int argument, but it's guaranteed that int and unsigned int have the same representation for values that are in the range of both. This:
printf("Length: %u\n", (unsigned int)MyStrlen(str));
is better, since %u expects an unsigned int argument.
The correct format for size_t is "%zu":
printf("Length: %zu\n", MyStrlen(str));
but this is a "new" feature in C99, and there are likely still some implementations that don't support it. (In particular, Microsoft has been very slow to support C99.) For maximum portability (assuming your string is no more than 232-1 bytes long) you can use this:
printf("Length: %lu\n", (unsigned long)MyStrlen(str));
This answers the question you asked about printf; pb2q ably diagnosed the actual cause of the problem you're seeing (and beat me to it!).

Resources