Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incorrect result for %p when implementation printf

Tags:

c

printf

I'm working on my own printf code and I got 2 problems that I hoped you might be able to help me with.

The first one is with the %p option :

This option gives me the pointer address of a void* in hex form. So what I'm doing is this :

void    printp(void *thing)
{
    dectohex((long)&thing, 1);
}  

where dectohex is just a function converting a decimal to hex. The result will always be correct, except for the last 3 characters. Always. For example :

me : 0x5903d8b8 , printf : 0x5903da28.

And these characters don't change very often, whereas the other part changes at each call like its supposed to.

The other problem I have is with the %O option. I can't manage to convert a signed int to an unsigned int. printf prints huge numbers for negative int's, and no casts seems to work since I wouldn't have the place to store it anyways.

EDIT: Thanks sooo much for the answers, so apparently for the first problem i was just a little stupid. For the second question i'm gonna try the different solutions you gave me and update you if i manage to do it.

Again thanks so much for your time and patience, and sorry for the delay in my response, i checked the email alert for any answer but it doesn't work apparently.

REEDIT: After reading your answers to my second question more carefully, i think some of you think i asked about %o or %0. I was really talking about %O as in %lo i think. In the man it tells me "%O : The long int argument is converted to unsigned octal". My problem is before converting the long int to octal, i need to convert it to something unsigned.

like image 306
madraven Avatar asked Dec 16 '14 13:12

madraven


People also ask

What does %P do in printf?

In C we have seen different format specifiers. Here we will see another format specifier called %p. This is used to print the pointer type data.

What is %P in C programming?

%p is for printing a pointer address. 85 in decimal is 55 in hexadecimal. On your system pointers are 64bit, so the full hexidecimal representation is: 0000000000000055.


3 Answers

If uintptr_t/intmax_t is defined (it is optional), convert the pointer to that integer type and then print.

Otherwise, if sizeof(uintmax_t) >= sizeof (void *) , convert to uintmax_t. uintmax_t is a required type, but may not be sufficiently large.

void printp(void *thing) {
  uintptr_t j = (uintptr_t) thing;
  char lst[(sizeof j * CHAR_BIT + 3)/ 4 + 1]; // Size needed to print in base 16
  char *p = &lst[sizeof lst] - 1;
  *p = '\0';
  do {
    p--;
    *p = "0123456789ABCDEF"[j%16];
    j /= 16;
  } while (p > lst);
  fputs(p, stdout);
}

The %O problem is likely a sign extension issue. (@mafso) Insure valuables used are unsigned, like unsigned and unsigned long. Without seeing the code difficult to know for sure.

like image 137
chux - Reinstate Monica Avatar answered Sep 21 '22 14:09

chux - Reinstate Monica


About the first issue you're having, just to make sure, you want to print the address of thing (note that thing itself is a pointer) or the address of the origin of thing (the pointer to the pointer thing)?

You're currently printing the pointer to the pointer.

Change

dectohex((long)&thing, 1); 

to

dectohex((long)thing, 1); 

if that is the case.

About the %O problem, can you give a code example?

like image 36
Ishay Peled Avatar answered Sep 21 '22 14:09

Ishay Peled


You need "unsigned long long" for your cast.

Pointers are unsigned, but long is signed.

The number of bits in any data type is implementation-dependent; however these days it is common for long and unsigned long to be 32 bits.

edit: to be more clear, you can't count on anything about the number of bits in C, C++ or Objective-C, it's always implementation-dependent. For example it was at one time common to have nine bit bytes and thirty-six bit words. That's why the Internet Protocols always specify "octets" - groups of eight bites - rather then "bytes".

That's one advantage of Java, in that the number of bits in each data type is strictly definited.

like image 39
Mike Crawford Avatar answered Sep 21 '22 14:09

Mike Crawford