How to printf a memory address in C - c

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.

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.

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

Related

how to printf 0x0000000 instead of (nil) and 0x08ffffff instead of 0x8ffffff in c

I am trying to use the stdout stream to print 0x00000000 instead of (nil) and 0x08ffffff instead of 0x8ffffff.
So basically, char *ptr1 = 0x00000000 and char *ptr2 = 0x08ffffff.
When I run
printf("start of address is %p and end of address is %p", ptr1, ptr2);
I get
start of address is (nil) and end of address is 0x8ffffff
I actually found a way around this and I would actually do this:
char *ptr1 = 0x00000000;
char *ptr2 = 0x08ffffff;
printf("start 0x%08x and end 0x%08x\n",ptr1, ptr2);
This generates
start 0x00000000 and end 0x08ffffff
However, the compiler sends the following warning:
warning: format ‘%x’ expects argument of type ‘unsigned int’,
but argument 3 has type ‘void *’ [-Wformat=]
How should I modify printf to adjust the output print?
First, to have any control over how addresses are printed, you must convert them to an integer type. The specifications for printing pointers with %p are inadequate. To do this, you can include <stdint.h> and use the type uintptr_t, which is an unsigned integer type suitable for some work with addresses.
Second, the header <inttypes.h> provides a macro PRIxPTR that provides a printf conversion specifier for printing uintptr_t values in hexadecimal.
Third, you can add a flag 0 and a minimum field width 8 to request the conversion pad with zeros to at least eight digits.
Here is sample code:
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
static void PrintAddress(const void *p)
{
uintptr_t u = (uintptr_t) p;
printf("0x%08" PRIxPTR, u);
}
int main(void)
{
char *ptr1 = (char *) 0x00000000;
char *ptr2 = (char *) 0x08ffffff;
printf("Start of address is ");
PrintAddress(ptr1);
printf(" and end of address is ");
PrintAddress(ptr2);
printf(".\n");
}
Better yet, you can adapt the field width to the size of uintptr_t in your C implementation by including <limits.h> and calculating the number of digits needed:
printf("0x%0*" PRIxPTR, ((int) sizeof u * CHAR_BIT + 3) / 4, u);
Note that directly setting pointers to hard-coded constant values, as you do with the initializations of ptr1 and ptr2, is rare. It is generally used in doing special things with hardware. When you are deliberately converting an integer to a pointer, you should use a cast to avoid a compiler warning.

Basic C Pointers

For some reason when I try to compile this code in the C program it is giving me back an error. I am trying to print out the actual memory address of variable x. If anyone knows I would appreciate it!
Code:
int x = 7;
printf("x is %d\n", x);
x = 14;
printf("x is %d\n", x);
int *aptrx = malloc(sizeof(int));
aptrx = &x;
printf("aptrx is %x\n", aptrx);
Error:
*pointer.c:12:29: error: format specifies type 'unsigned int' but the argument has type* 'int \*' [-Werror,-Wformat]
You do not need to have this line in your code if you just want to print the address of x.
int *aptrx = malloc(sizeof(int));
You do not need to allocate memory whenever you create a pointer variable. If you want to point to an existing variable, which you want in this case, you can simply do
int *aptrx = &x;
Then try to print the address using below line using the format specifier %p.
printf("aptrx is %p\n", aptrx);
You are having an error because the format expects an unsigned int but the argument is an int *.
The manual for printf says about the %x conversion specifier:
The unsigned int argument is converted [...] to unsigned hexadecimal (x and X)
notation.
If you want to print a pointer, you can use the %p conversion specifier.
The void * pointer argument is printed in hexadecimal (as if by %#x
or %#lx).
Like this:
printf("aptrx is %p\n", aptrx);
It's not necessary to allocate memory dynamically to create a pointer variable.
int *aptrx = malloc(sizeof(int)); //unnecessary
Simply, create a pointer variable just like any other variable
int *aptrx = &x;
To print out the value of the pointer (i.e. address of x), use the format specifier %p or %u:
printf("aptrx is %p\n", aptrx);

while giving string value to integer what is happening?

In my C program i assign a string in one integer variable and i print with percentage %s it will print that string with warning integer to pointer without cast and print with %d it print 134513904 then i change my string value and print with %d "134513904" is printing what is this value and how integer variable storing a string value in int variable?
enter code here
#include<stdio.h>
main()
{
int a="naveen";
printf("%d\n",a);
printf("\n%s\n",a);
if("naveen")
{
printf("hi");
}
int_point.c: In function ‘main’:
int_point.c:22:8: warning: initialization makes integer from pointer without a cast [enabled by default]
int a="naveen";
^
int_point.c:24:2: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
printf("\n%s\n",a);
^
134513920
naveen
hi
The following assigns a pointer (not a string) to s:
const char *s = "navven";
That means the following assigns a pointer (not a string) to a:
int a = "naveen";
Computers don't really see a difference between a pointer and number. They're both things that fit in their registers. And some people take advantage of that fact. So while the compiler warns you that you are doing something wrong, it still lets you treat the pointer as a number.
So a is ends up with the value of the pointer if it were an int. That's not safe to do. Not quite. While you can't use an int safely, you can use an intptr_t safely.
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
int main(void) {
const char *p1 = "naveen";
printf("%p %s\n", p1, p1);
intptr_t i = (intptr_t)p1;
printf("0x%" PRIxPTR "\n", i);
const char *p2 = (const char*)i;
printf("%p %s\n", p2, p2);
return 0;
}
Output:
0x51ee878764 naveen
0x51ee878764
0x51ee878764 naveen

warning: format ‘%x’ expects argument of type ‘unsigned int’

When I try and compile this I get the following error, not sure why...
warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘char *’ [-Wformat=]
printf("Name buffer address: %x\n", buffer);
The code:
#include <string.h>
#include <stdio.h>
main(){
char name[200];
printf("What is your name?\n");
scanf("%s", name);
bo(name, "uname -a");
}
int bo(char *name, char *cmd){
char c[40];
char buffer[40];
printf("Name buffer address: %x\n", buffer);
printf("Command buffer address: %x\n", c);
strcpy(c, cmd);
strcpy(buffer, name);
printf("Goodbye, %s!\n", buffer);
printf("Executing command: %s\n", c);
fflush(stdout);
system(c);
}
You are getting the warnings because of the following statements
printf("Name buffer address: %x\n", buffer);
printf("Command buffer address: %x\n", c);
%x expects an unsigned int, whereas you're supplying a pointer.
To refer, C11 standard, chapter §7.21.6.1
o,u,x,X The unsigned int argument is converted to unsigned octal (o), unsigned
decimal (u), or unsigned hexadecimal notation (x or X) in the style dddd; [...]
Supplying invalid argument invokes undefined behavior.
You should be using %p to print the address
p The argument shall be a pointer to void.[...]
and cast the argument to void *, because for pointer types no default argument promotion takes place.
Having said that,
main() should be int main(void), at least, to conform to the standard.
You need to forward declare your function bo() because implicit declarations are bad and non-standard now.
To print an address use "%p" instead of "%x". You also need to cast to void *
printf("Name buffer address: %p\n", (void *) buffer);

printf formatting (%d versus %u)

What is difference between %d and %u when printing pointer addresses?
For example:
int a = 5;
// check the memory address
printf("memory address = %d\n", &a); // prints "memory address = -12"
printf("memory address = %u\n", &a); // prints "memory address = 65456"
You can find a list of formatting escapes on this page.
%d is a signed integer, while %u is an unsigned integer. Pointers (when treated as numbers) are usually non-negative.
If you actually want to display a pointer, use the %p format specifier.
%u prints unsigned integer
%d prints signed integer
to get a pointer address use %p
Other List of Formatting Escapes:
Here are the full list of formatting escapes. I am just giving a screen shot from this page
If I understand your question correctly, you need %p to show the address that a pointer is using, for example:
int main() {
int a = 5;
int *p = &a;
printf("%d, %u, %p", p, p, p);
return 0;
}
will output something like:
-1083791044, 3211176252, 0xbf66a93c
%u is used for unsigned integer. Since the memory address given by the signed integer address operator %d is -12, to get this value in unsigned integer, Compiler returns the unsigned integer value for this address.
The difference is simple: they cause different warning messages to be emitted when compiling:
1156942.c:7:31: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
printf("memory address = %d\n", &a); // prints "memory add=-12"
^
1156942.c:8:31: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 2 has type ‘int *’ [-Wformat=]
printf("memory address = %u\n", &a); // prints "memory add=65456"
^
If you pass your pointer as a void* and use %p as the conversion specifier, then you get no error message:
#include <stdio.h>
int main()
{
int a = 5;
// check the memory address
printf("memory address = %d\n", &a); /* wrong */
printf("memory address = %u\n", &a); /* wrong */
printf("memory address = %p\n", (void*)&a); /* right */
}

Resources