How to printf a memory address in C

CPointersPrintfMemory AddressUnary Operator

C Problem Overview


My code is:

#include <stdio.h>
#include <string.h>

void main()
    {
    char string[10];
    int A = -73;
    unsigned int B = 31337;

    strcpy(string, "sample");

    // printing with different formats
    printf("[A] Dec: %d, Hex: %x, Unsigned: %u\n", A,A,A);
    printf("[B] Dec: %d, Hex: %x, Unsigned: %u\n", B,B,B);
    printf("[field width on B] 3: '%3u', 10: '%10u', '%08u'\n", B,B,B);

    // Example of unary address operator (dereferencing) and a %x
    // format string 
    printf("variable A is at address: %08x\n", &A);

I am using the terminal in linux mint to compile, and when I try to compile using gcc I get the following error message:

basicStringFormatting.c: In function ‘main’:
basicStringFormatting.c:18:2: warning: format ‘%x’ expects argument
of type ‘unsigned int’, but argument 2 has type ‘int *’ [-Wformat=]
printf("variable A is at address: %08x\n", &A);

All I am trying to do is print the address in memory of the variable A.

C Solutions


Solution 1 - C

Use the format specifier %p:

printf("variable A is at address: %p\n", (void*)&A);

The standard requires that the argument is of type void* for %p specifier. Since, printf is a variadic function, there's no implicit conversion to void * from T * which would happen implicitly for any non-variadic functions in C. Hence, the cast is required. To quote the standard:

7.21.6 Formatted input/output functions (C11 draft)

> p The argument shall be a pointer to void. The value of the pointer is > converted to a sequence of printing characters, in an > implementation-defined manner.

Whereas you are using %x, which expects unsigned int whereas &A is of type int *. You can read about format specifiers for printf from the manual. Format specifier mismatch in printf leads to undefined behaviour.

Solution 2 - C

A workaround to use %x with length specifier to print an int or unsigned int without compiler complaining about casting would be to use malloc:

unsigned int* D = malloc(sizeof(unsigned int)); // Allocates D
unsigned int D_address = *((unsigned int*) &D); // D address for %08x without warning
*D = 75; // D value
printf("variable D is at address: %p / 0x%08x with value: %u\n", D, D_address, *D);

Alternatively you can compile with gcc -w flag to suppress those casting warnings.

Edit for 64-bit addresses:

unsigned long* D = malloc(sizeof(unsigned long)); // Allocates D
unsigned long D_address = *((unsigned long*) &D); // D address for %016lx without warning
*D = ULONG_MAX; // D value
printf("variable D is at address: %p / 0x%016lx with value: %lu\n", D, D_address, *D);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionvarlotbarnacleView Question on Stackoverflow
Solution 1 - CP.PView Answer on Stackoverflow
Solution 2 - ChmofradView Answer on Stackoverflow