1

I am receiving warnings when compiling my code. These warnings include: format %lu expects argument of type 'long unsigned int' but argument 3 has type long long unsigned int & cast from printer to integer of different size.

I don't seem to know what is wrong. Any advice on how to fix this is much appreciated.

void printBits(size_t const size, void const * const ptr);


int main()
{

// variables are not in order on purpose for the first step in running the code.

float c;
char a;
double d;
int b;

d = 561232019;       /* 8 bytes */
c = 154.6;           /* 4 bytes */
b = -83273;          /* 4 bytes */
a = 42;              /* 1 byte */




printf("\n--------------------------------------------\n");

printf("LABEL  -  ADDRESS(hex)    ADDRESS (dec) [S - E]  -  BINARY\n"); 
printf("A -      ");
printf("%p  -   ",&a);
printf("%lu -  %lu         ",(long)&a, (long)&a + sizeof(a)-1); // the two errors occur at      
//this line as well as the other identical print statements for each variable used. This print 
//statement is identical to when using b, c, d and all have the same warnings. I just used this part 
//of code to find out how to fix this error so I could fix all the other identical print statements. 

printf("%d -        ",a);
printBits(sizeof(a), &a);
printf("\n--------------------------------------------\n");
Brett Hale
  • 21,653
  • 2
  • 61
  • 90
azwahd180
  • 21
  • 1
  • 2
  • Note that `sizeof a` will be 1 on all standard conforming platform, so `sizeof(a)-1 == 0`. C99 6.5.3.4 The sizeof operator - 3: _When applied to an operand that has type char, unsigned char, or signed char, (or a qualified version thereof) the result is 1...._ – 12431234123412341234123 Sep 25 '20 at 10:13

1 Answers1

2

The expression with sizeof(a) will likely promote the result to that of size_t - which is obviously an unsigned 64-bit type on this platform. I suspect you're using Windows (WIN64), where long is 32 bits. see: LLP64. So you will need %llu.

Note that you could use also use %zu for a size_t argument. Truncating addresses to a 32-bit %lu is likely incorrect too. You are using 64-bit pointers. Use %p. A careful reading of the C stdio *printf spec might be useful.


@Antii's comment also worth considering: You can safely cast an address to uintptr_t (the converse is not so straightforward), and take advantage of the <inttypes.h> PRIxPTR format qualifier. In theory, this is an optional type, but will exist on any normative platform.


Here are some examples: (I hope they're right - I'm assuming 64-bit pointers, but have only briefly tested them)

#include <inttypes.h>
#include <stdio.h>

int main (void)
{
    char a = 42;

    // asserts: sizeof(unsigned long long) >= sizeof(char *)
    // 64-bit unsigned values and 64-bit hexadecimal values:

    printf("%llu - %llu\n", (unsigned long long) (& a), (unsigned long long) (& a + sizeof(a) - 1));
    printf("%llx - %llx\n", (unsigned long long) (& a), (unsigned long long) (& a + sizeof(a) - 1));
    printf("\n");

    // use of `uintptr_t` and C string macro concatenation:
    // hexadecimal uintptr_t values with and without leading zeroes.

    const char *fmt = "%" PRIxPTR " - %" PRIxPTR "\n";
    printf(fmt, (uintptr_t) (& a), (uintptr_t) (& a + sizeof(a) - 1));

    printf("0x%016" PRIxPTR " - 0x%016" PRIxPTR "\n", (uintptr_t) (& a), (uintptr_t) (& a + sizeof(a) - 1));
    printf("\n");

    // finally the most 'elegant' solution: (unpadded) hexadecimal values:

    printf("%p - %p\n", & a, & a + sizeof(a) - 1);

    return (0);
}

note: @KamilCuk raised an important point: technically, %p is only defined for (void *) arguments. This is unlikely to be an issue on anything but ancient / exotic platforms - but it is part of the specification. see this question.

Brett Hale
  • 21,653
  • 2
  • 61
  • 90
  • I tried changing the %lu to %llu & %zu and the same errors keep returning. And yes, I am using WIN64. I just don't know what to change in that print statement to fix the error. – azwahd180 Sep 25 '20 at 10:33
  • for this section: (long)&a + sizeof(a)-1), I just enclosed &a with a bracket with +sizeof(a)-1) to get (long) (&a + sizeof(a)-1). This got ride of the "%lu error for some reason, I don't know why or how, but the "cast from printer to integer of different size" error is still there. – azwahd180 Sep 25 '20 at 10:38
  • 1
    @azwahd180 - are you still casting an address to `(long)`? If so, that's truncating a 64-bit address to a 32-bit value on the WIN64 ABI. Furthermore, you should be casting to an **`unsigned`** type. e.g. `(unsigned long long)` or `(uintptr_t)`. `(long)` is signed - and the format specifier expects an unsigned type / expression. – Brett Hale Sep 25 '20 at 10:39
  • I changed the casting address to both '(unsigned long long)' and '(uintptr_t)' but I keep on receiving the same error as well as a new one stating that there are too many arguments. I currently now have 'printf("%lu - %lu ",(long)&a, (long)(&a + sizeof(a)-1)). Also changed the %lu to %llu. – azwahd180 Sep 25 '20 at 10:53
  • My point being - you are passing a `(long)` (a *signed* long) to a format specifier `%lu` that expects an `(unsigned long)`. – Brett Hale Sep 25 '20 at 11:03
  • @azwahd180 - I've appended some minimal examples to my answer. I hope you can work through them and understand what each `printf` (and formats) are doing... – Brett Hale Sep 25 '20 at 11:27
  • Och! I see why I did not get it. In `The expression with sizeof(a)` you refer to _this expression_: `(long)&a + sizeof(a)-1`. I was thinking like `sizoef(a)` as _being_ the whole expression - thus my confusion, my fault, nevermind then, – KamilCuk Sep 25 '20 at 12:02