简体   繁体   中英

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 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");

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM