I am trying to create a pointer to an address in memory given by the user, but I am having problems. I actually manage to create the pointer and print its address, but I never succeed to print or change its content. Would any one kindly explain why?
Here is the code I'm trying to run:
int m = 10;
printf("&m = %d (address in dec.)\n", &m);
printf("Enter an address: ");
int address;
scanf("%d", &address);
int* p = (int*) address;
printf("p = %d (address in dec.)\n", p);
printf("*p = %d (value)\n", *p);
and here is a console of me interacting with the program:
&m = 1220033252 (address in dec.)
Enter an address: 1220033252
p = 1220033252 (address in dec.)
Segmentation fault
Same thing happens if I try an address different from &m.
Thanks!
int is not necessarily big enough to hold a pointer. It's usually 32 bits, but pointers are 64 or 128 bits on many systems now.
You can use the built-in typedef intptr_t to declare an integer big enough to hold a pointer to integer.
int m = 10;
printf("&m = %" PRIiPTR " (address in dec.)\n", (intptr_t)&m);
printf("Enter an address: ");
intptr_t address;
scanf("%" SCNiPTR, &address);
int* p = (int*) address;
printf("p = %" PRIiPTR " (address in dec.)\n", (intptr_t)p);
printf("*p = %d (value)\n", *p);
For more information, see Why / when to use `intptr_t` for type-casting in C? and string format for intptr_t and uintptr_t
Shortly, you're hitting the fact that int and int * aren't the same types.
First, %d should be used for values of type int, which as not the same as pointer type. Most likely, on your machine size of pointer is bigger than size of int, so you are printing not the pointer, but just a part of it. For example, in my case the pointer value is 140734913221608 (0x7fff668293e8), but 1719833576 (0x668293e8) gets printed. Because of that, you enter a pointer to a random unallocated memory, and when you dereference it, segmentation fault occurs.
Second, the code for reading pointer value has the same problem. Additionally to wrong format string for scanf, you are trying to store the value in a variable of type int. A variable of pointer type should be used instead.
As for getting the code working, check out Correct format specifier to print pointer or address? for an in-depth explanation.
Related
In the program
#include<stdio.h>
struct t {
char a[5];
char b[];
} temp;
int main(){
temp.b[0] = 'c';
temp.b[1] = 'b';
temp.b[2] = '\0';
printf("Size of struct = %lu\n", sizeof(temp));
printf("String is %s\n", temp.b);
printf("Address of temp = %p\n", &temp);
printf("Address of array a = %p\n", &(temp.a));
printf("Address of b = %p\n", &(temp.b));
}
with output
Size of struct = 5
String is cb
Address of temp = 0x601035
Address of array a = 0x601035
Address of b = 0x60103a
In this program, how exactly is array b being allocated? How long is it? Is this some undefined behavior, which is only succeeding in the dummy program as I am not doing anything else. Running into gdb, I can access some memory locations initialized as zero, which makes me suspect that it is allocating some memory.
I do have an api that requires me to format one element of struct as int a[][SIZE], and I am confused about that.
Also, why is sizeof not taking into account at least something from array b. I am not sure if it is taking it as an array or pointer.
The way you use it is undefined behavior. To answer your immediate question, with static or automatic storage (as you use it), this member has a size of 0. So any index will be invalid. It "seems" to work in your experiment, but remember, c doesn't do any bounds checking. In fact, you're doing invalid writes and you're just lucky your example doesn't crash and burn.
Such a member is only allowed as last member of a structure and the reason for this is you can use it with dynamic storage:
struct t *temp = malloc(sizeof(struct t) + 5 * sizeof(char));
will allocate an instance of struct t with temp->b being an array of char of size 5.
I know there's tons of these and it's probably a simple question, but I can't seem to figure it out :(
char * char_buffer = (char *) malloc(64);
printf("%x\n", char_buffer);
memset(char_buffer,
0,
64);
printf("%x\n", char_buffer);
Output :
50000910
50000910
Why isn't char_buffer zero'd? Can someone explain what's happening?
You are confused about the difference between a pointer and space being pointed to.
Your code doesn't zero the pointer. It zeroes the space being pointed to. The memset function behaves that way. In fact you would not want to zero the pointer, as then it would no longer point to the memory you allocated.
Your printf statement attempts to print the pointer's value, which is the address of the space being pointed to. Not the contents of the space being pointed to.
Actually the printf statement causes undefined behaviour, because you mismatched format specifiers. Your compiler should have warned about this.
Here is some correct code:
printf("The buffer's address is %p\n", char_buffer);
printf("The buffer contains: %02X %02X %02X ...\n",
(unsigned char)char_buffer[0],
(unsigned char)char_buffer[1],
(unsigned char)char_buffer[2]);
To use the %X specifier you must pass non-negative values in, which is why the cast is necessary. You could declare the buffer as unsigned char * instead, in which case the cast would not be necessary.
You're printing the address of the buffer, not its contents. The contents are zero after the memset(). Just try:
printf("%d", char_buffer[0]);
and see the zero ;)
You're printing out the pointer, not the buffer values.
memset(p,v,n) writes the byte v to the byte pointed at by p and n-1 bytes after it. It doesn't touch the pointer p at all (it's passed in by value, how can it?)
To print out the buffer, you'd have to loop through it. I use something like this:
void printbuf(char *buf, int size)
{
int i = 0;
char b = 0;
for (i = 0; i < size; i++) {
if (i % 8 == 0) {
printf("\n%3d: ", i);
}
b = buf[i];
printf("%2hhX ", b);
}
}
I want to print out things from given memory addresses.
Using this code, I can define a variable, define a pointer to it and print its contents using the pointer.
char buf[100];
void *p = buf;
strcpy(p, "Test string");
printf("Address: %X\n", &buf);
printf("Contents: %c\n", p);
What I want to do is to specify a certain memory address, and print out the contents of that block. I tried experimenting by incrementing and decremeting p, but it doesn't print out anything.
An interesting little problem. One that should occur to every programmer sooner or later, either out of curiosity or cussedness.
Essentially four parts.
Express the address you want as an integer of the appropriate size.
Cast the integer into a pointer to some type.
Dereference the pointer to get a value of that type.
Print the value.
[if desired, increment address and repeat.]
For simplicity I'll use an address of 0x1000 and integer contents.
int address = 0x1000;
int* pcontent = (int*)address;
int content = *pcontent;
printf ("Address %p: content %08x\n", pcontent, content);
Two points should be made.
This is undefined behaviour, but inevitable if you want to get a result.
The address I chose could be valid memory or could trigger a trap error or it could do just about anything. You'll have to experiment with different addresses to find out which.
[Many years ago I used this strategy to print out the entire contents of memory on a machine that had just 96KB of memory, which led to some interesting hacking possibilities. But I digress.]
You are using wrong specifier to print the address. Use %p and cast argument to void *.
printf("Address: %p\n", (void*)buf);
and to print string
printf("Contents: %s\n", p);
You have to define pointer p as
char *p = buf;
or to use casting then incrementing p. For example
p = ( char *)p + n;
For example
printf( "%s\n", ( char *)p + 5 );
You may not increment/decrement pointers of type void * because void in incomplete type.
Also the format specifiers in these calls
printf("Address: %X\n", &buf);
printf("Contents: %c\n", p);
are wrong.
If you want to print out a string you have to specify %s. if you wnat to print only one character then you should write
char *p = buf;
printf("Contents: %c\n", p[0]);
or
void *p = buf;
printf("Contents: %c\n", ( ( char *)p )[0]);
You are using %c instead use %s to print string printf("Contents: %s\n", p);
If we wanted to print random bytes from around memory, we would want to use:
char *p = buf;
printf("Address: %p\n", p);
printf("Contents: 0x%02x\n", *p);
Let's note though, that given a random address, dereferencing it can cause the application to fail. You can not assume that all of the memory space is valid.
You could try something like this:
void printMemory(void* mem, int bytes){
char* p = (char*) mem;
for(int i=0;i<bytes;i++){
printf("%x ",p[i] & 0xff);
if(i%8 == 7)
printf("\n");
}
}
This will print 8 bytes per row.
Pointer Downcast
int* ptrInt;
char * ptrChar;
void* ptrVoid;
unsigned char indx;
int sample = 0x12345678;
ptrInt = &sample;
ptrVoid = (void *)(ptrInt);
ptrChar = (char *)(ptrVoid);
/*manipulating ptrChar */
for (indx = 0; indx < 4; indx++)
{
printf ("\n Value: %x \t Address: %p", *(ptrChar + indx), ( ptrChar + indx));
}
Output:
Value: 00000078 Address: 0022FF74
Value: 00000056 Address: 0022FF75
Value: 00000034 Address: 0022FF76
Value: 00000012 Address: 0022FF77
Question:
Why was sample divided into char sized data? And when pointer arithmetic is performed, how was it able to get its remaining value?
How this was possible?
Pointer Upcast
unsigned int * ptrUint;
void * ptrVoid;
unsigned char sample = 0x08;
ptrVoid = (void *)&sample;
ptrUint = (unsigned int *) ptrVoid;
printf(" \n &sample: %p \t ptrUint: %p ", &sample, ptrUint );
printf(" \n sample: %p \t *ptrUint: %p ", sample, *ptrUint );
Output:
&sample: 0022FF6F ptrUint: 0022FF6F
sample: 00000008 *ptrUint: 22FF6F08 <- Problem Point
Question:
Why is it that there is a garbage value in *ptrUint? Why is the garbage value similar
to ptrUint? Should malloc() or calloc() be used to avoid this garbage value? What kind of remedy would you suggest to remove the garbage value?
In the first example, you are using a char pointer so the data is going to be accessed a byte at a time. Memory is byte addressable, so when you add one to a pointer, you will access the next higher memory address. This is what is happening with the for loop. Using a byte pointer tells the compiler to access only the single byte, and rest of bits will show up as 0 when you are printing with %p.
In the second example, I think what is happening is that one byte is allocated for the sample byte, then the following 4 bytes were allocated to the ptrUint. So when you get the value starting at the memory address of sample and converting it to a 4 byte pointer, you just see the value in Sample plus the first 3 bytes of the ptrUint. If you cast this to a char pointer, and print, you would only see 8 in the output.
These aren't upcasts and downcasts, that would imply some kind of inheritance hierarchy.
In your first example you treat a pointer to an integer like if it was a pointer to char(s). Incrementing a pointer to int adds 4 to it, incrementing a pointer to char adds 1 to it (assuming 32 bit ints and 8 bit chars). Dereferencing them makes an int and a char, respectively. Hence the fragmentation into bytes.
In your second example you treat the unsigned char variable called sample as if it were a pointer to int, and dereference it. You are essentially reading garbage from the 0x08 memory address. I suppose you forgot a &. You are also passing a 1 byte char and a 4 byte int to the second printf, instead of 4+4 bytes, that messes up printf, reading 3 bytes more from the stack than you have given him. Which coincidentally is part of the ptrUint value given to the first call of printf. Using %c instead of %p should fix it.
The other answers have already explained why you're seeing what you're seeing.
I will add that your second example relies on undefined behaviour. It is not valid to dereference an int * that points to data that wasn't originally an int. i.e.:
char x = 5;
int *p = (int *)&x;
printf("%d\n", *p); // undefined behaviour
For debugging reasons, how can one in a C program print some memory address?
For instance, how should I do to print the content of address 0x611268 in form of a 4 byte float?
I know I could use a debugger, but I mean, to print out in screen.
More correctly, printf("Value = %f\n", *((float*)0x611268));
Of course this assumes the address you've given is in the address space of the process running the printf.
#include <stdio.h>
int main(void)
{
// pointer to int (4bytes) that points to memory address 0x611268
int* address = (int *)0x611268;
printf("Memory address is: 0x%x\n", address);
// Note that this address should exist on your process' memory or
// the line below will cause a Segmentation Fault
*address = 0xdead; //assign a value to that address
printf("Content of that address is: 0x%x\n", *address);
return 0;
}
The correct format specifier to print out contents of pointers is "%p":
fprintf(stderr, "myVar contains %p\n", (void*)myVar);