I have started learning C (so, you know.. pointers).
I have this code:
#include <stdio.h>
#include <string.h>
int main (int argc, char* argv[])
{
char c = 'c';
char* cptr = &c;
printf("c = %c\n", c);
printf("*cptr = %c\n", *cptr);
printf("c address = %p\n", &c);
}
My output is:
c = c
*cptr = c
c address = 0x7fff0217096f
When I convert the hexadecimal above to decimal, I get: 140720994002157
My questions:
1) Does this decimal value represent the memory address? Isn't it too big?
2) How can I print the value of the pointer (which means the address of the c variable) as a decimal?
Isn't [the address] too big?
This is a virtual address, meaning that its numerical value does not necessarily represent the sequential number of the byte in physical memory. Moreover, different processes may keep different data at the same virtual address, because each one has its individual address space.
How can I print the value of the pointer in an integer format?
Use uintptr_t to represent the pointer as an integer value, then print using PRIuPTR macro:
#include <stdio.h>
#include <inttypes.h>
int main(void) {
char c = 'x';
char *p = &c;
uintptr_t x = (uintptr_t)p;
printf("Pointer as decimal: %"PRIuPTR"\n", x);
return 0;
}
Demo.
1). You should print the address as printf("c address = %p\n", &c);. Now you attempt to print the address where the pointer variable itself is stored, which probably doesn't make much sense.
That being said, it might still be a valid address, assuming 64 bit addresses.
2). You will have to safely convert it to an integer which is guaranteed to be large enough to contain a pointer address:
#include <inttypes.h>
printf("c address = %" PRIuPTR "\n", (uintptr_t)&c);
Related
I am learning C. As I went through pointers there I noticed some strange behavior which I can't get it. When casting character pointer to integer pointer, integer pointer holds some weird value, no where reasonably related to char or char ascii code. But while printing casted variable with '%c', it prints correct char value.
Printing with '%d' gives some unknown numbers.
printf("%d", *pt); // prints as unknown integer value that too changes for every run
But while printing as '%c' then
printf("%c", *pt); // prints correct casted char value
Whole Program:
int main() {
char f = 'a';
int *pt = (int *)&f;
printf("%d\n", *pt);
printf("%c\n", *pt);
return 0;
}
Please explain how char to int pointer casting works and explain the output value.
Edit:
If I make the below changes to the program, then output will be as expected. Please explain this too.
#include <stdio.h>
int main() {
char f = 'a';
int *pt = (int *)&f;
printf("%d\n", *pt);
printf("%c\n", *pt);
int val = (int)f;
printf("%d\n", val);
printf("%c", val);
return 0;
}
Output:
97
a
97
a
Please explain this behavior too.
For what the C language specifies, this is just plain undefined behavior. You have a char sized region of memory from which you are reading an int; the result is undefined.
As for what is likely happening: The C runtime ends up dumping some random garbage on the stack before main is even executed. char f = 'a'; happens to rewrite one byte of the garbage to a known value, but the padding to align pt means the remaining bytes are never rewritten at all, and have "whatever the runtime left behind" in them. So when you read an int out, on a little endian system, the low byte equals the value of 'a', but the high bytes are whatever garbage happens to be left in the padding space.
As for why %c works, since the low byte is still the same, and %c only examines the low byte of the int provided, all the garbage is ignored, and things happen to work as expected. This only works on a little endian machine though; on a big endian machine, it would be the high byte initialized to 'a', but the low byte (garbage) would be printed by %c.
You have define f as a char. This allocates typically 1 byte of storage in most of the hardware. You take the address of f, cast it to (int *) and assign it to an int * variable, pt. Size of integer depends on the underlying hardware - it could be 2 or 4 or even more. When you assign address of f to pt, the address that gets assigned to pt depends on factors such as int size and the alignment requirements. That is why when you print *pt, you see a garbage value. Actually, the ASCII value of 'a' is contained in the garbage, the position of which depends on the int size, endianness of the hardware, etc. If you print *pt with %x, you will see 61 in the output (61 hex is 97 in decimal).
<#include <stdio.h>
int main()
{
//type casting in pointers
int a = 500; //value is assgned
int *p; //pointer p
p = &a; //stores the address in the pointer
printf("p=%d\n*p=%d", p, *p);
printf("\np+1=%d\n*(p+1)=%d", p + 1, *(p + 1));
char *p0;
p0 = (char *)p;
printf("\n\np0=%d\n*p0=%d", p0, *p0);
return 0;
}
#include <stdio.h>
int main () {
char c = 'A';
int *int_ptr;
double *double_ptr;
*int_ptr = *(int *)&c;
*double_ptr = *(double *)&c;
printf("Original char = %c \n", c);
printf("Integer pointer = %d \n", *int_ptr);
printf("Double pointer = %f\n", *double_ptr);
return 0;
}
The questing is – Why can't I assign the double_ptr using this code, because it causes segmentation fault, but works fine for integer?
As I understand char is 1-byte long and int is 4-bytes long, so double is 8 bytes-long.
By using expression *(double *)&c I expect the following:
& – Get the memory address of c.
(double *) – pretend that this is a pointer to double.
*() – get the actual value and assign it to double var.
Your code has Undefined Behaviour. Therefore anything could happen.
The UB is because you are casting a char which is one byte to types that are 4 and 8 bytes, which means you are (potentially) accessing memory out of bounds, or with the wrong alignment.
Whether any of this will "work" or "not work" on any particular system is not very relevant, because the code is erroneous.
In your program, typecast of char to int* or double* and then a dereference would get some number of extra bytes from memory, which is undefined behavior.
I am a first year student in C programming so my skill/knowledge is limited. I am trying to create my own implementation on printf, but I am having trouble with retrieving and printing the address of a variable. With printf, its possible to output the address of a variable with %p, i need to replicate %p somehow.
When storing the address of a variable, the data type is int*, and I cannot figure out how to write this address to the screen(stdout).
For Example:
int i = 123;
int *address = &i;
Now how would I output address(not the value at i)? I have tried using the original printf format specifiers for testing purposes. I tried using %x, %s, %d, %lu... it all gives me an error as I am trying to output an int*(integer pointer).
Can anyone assist me in outputting the address?
You can only inspect the bits of the pointer and print those, using the type unsigned char:
unsigned char* a = ( unsigned char* )address;
for( size_t i = 0 ; i < sizeof( address ) ; i++ )
printf( "%hhu" , a[i] );
Another option, if the pointer is a pointer to an object, is to cast the pointer to types: intptr_t or uintptr_t, but the availability of those types is implementation defined.
If it's for the address of an object you could do the following:
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main(void)
{
int a;
uintptr_t uip = (uintptr_t) ((void*) &a);
printf("address of a = 0x%"PRIXPTR, uip);
}
To print the address of a function you need to go as proposed here.
#include <stdio.h>
int main()
{
int i;
int buf[10];
char *p ;
p = 4;
printf("%d",p);
return 0;
}
Output:
4
How come it is 4? I was expecting some address value. Can you please help me understand it?
This is undefined behavior, because %d expects an integer.
The reason why you see this output is that pointers have enough capacity to store small integer numbers, such as 4. If by coincidence the pointer size on your system matches the size of an integer, printf would find a representation that it expects at the location where it expects it, so it would print the numeric value of your pointer.
The proper way to print your pointer would be with the %p format specifier, and a cast:
printf("%p", (void*)p);
I was expecting some address value.
You would get an address value if you had assigned p some address. For example, if you did this
char buf[10];
char *p = &buf[3];
printf("%p", (void*)p);
you would see the address of buf's element at index 3.
Demo.
Consider the following test program (codepad execution):
#include <stdio.h>
#include <string.h>
struct camp {
char b[8];
};
int main()
{
struct camp c;
strcpy(c.b, "Hello");
c.b[5] = '\0';
printf("c size: %d\nAddress (amp): %d :: %d\n", sizeof(c), &c, c);
printf("Address of b: %d :: %d\n", &(c.b), c.b);
return 0;
}
A sample output:
c size: 8
Address (amp): -1082463628 :: 1819043144
Address of b: -1082463628 :: -1082463628
Whereas the address given by &(c.b) and c.b (second call to printf) is same, the same for struct camp c (first call to printf) returns different address. Furthermore, &c being same as &(c.b) or c.b.
What exactly is happening?
What printf is trying to do in the first case is to interpret c as an integer. c is not an integer, or even a value that can be converted to an integer (explicitly or implicitly), so the value written can be anything as you are invoking undefined behavior.
There is only one data member in the struct hence you are seeing the same address for b as well as for c the struct object.
Also array name gives the address of the first element of that array.Hence , c.b will give the same address as &(c.b) since the later one is address of whole array.
&c &(c.b) and c.b will be same in your case but you are printing the c using %d format specifier , so you are seeing an undefined behaviour , The last argument is not the address of c (so you are getting garbage value).