I've seen a very strange code snippet and i am not quite sure if i understood it right:
#include <stdio.h>
int main(char *argc, char **argv)
{
char a[50];
*(char *) (a + 2) = 'b'; // <== THE LINE WHICH CONFUSES ME
printf("value: %c\n", a[2]);
return 1;
}
Is it right that we go 2 buckets further cast the 'b' into a pointer to the b and then dereference it?
That's exactly equivalent of
*(a + 2) = 'b';
The cast is unnecessary.
All it does is add two to the array-which-decays-to-a-pointer a, dereference the resulting pointer, and assign the character 'b' to that memory location.
When a is a pointer, the code a[x] is exactly equivalent of *(a + x). So in your case, *(a + 2) = 'b' is exactly the same as a[2] = 'b'.
*(char *) (a + 2)
is equivalent to
a[2]
By definition, a[2] is *(a + 2). The value of a + 2 is already of type char * so a cast of a + 2 to char *, as is (char *) (a + 2), is a no operation.
*(char *) (a + 2) = 'b'; // <== THE LINE WHICH CONFUSES ME
This line literally means the very same as
a[2] = 'b'
The first cast (char*) is redundant, since a is already of type char. And indexing in fact translates to addition and dereferenciation, i.e.
a[n] === *(a + n)
A little known fact about C: You could write as well
n[a]
and get the same result.
You aren't casting the 'b'.
You cast (a+2) to char* (Which does nothing, since it's already char*), deference it, and put there 'b'.
And yes, it is right that we go 2 buckets further.
No, you treat a as a pointer, increment it by two, then cast it to (char*) (useless cast, it already is char*), dereference it and then store 'b' into that.
It is exactly the same as this:
a[2] = 'b';
Related
Here's this code from the Art of Exploitation book by Jon Erikson. I understand the typecast on the second line makes the compiler leave you alone about data types. What I'm not sure about is why double typecasting is necessary on the bottom line.
int *int_pointer;
int_pointer = (int *) char_array;
for(i=0; i < 5; i++)
printf("[integer pointer] points to %p, which contains the char '%c'\n", int_pointer, *int_pointer);
int_pointer = (int *) ((char *) int_pointer + 1);
I am going to assume it's because leaving it like so without the (int *) would make it increment by the correct data type character, but is this not what you want? Why typecast back to int?
And what's up with the * inside the parenthesis? Is this de-referencing the data in the variable? Some explanation would be kindly appreciated.
It's not typecasting to int or char, it's typecasting the pointer to a char pointer or int pointer.
When you add one to a pointer, it advances to the next item being pointed at, by scaling the increment based on the type of the item.
If the items are int, it advances by the size of an int. This is probably 4 or 8 in the current environment but will hopefully will be larger in future so we can stop messing about with bignum libraries :-)
If the items are of type char, it advances by one (sizeof(char) is always one, since ISO C defines a byte as the size of a char rather than eight bits).
So, if you have four-byte int types, there's a big difference between advancing an int pointer and a char pointer. For example, consider the following code:
int *p = 0; // bad idea but shows the concept.
p = p + 1; // p is now 4.
p = (int*)(((char*)p) + 1) // p is now 5.
That last statement breaks down as:
(char*)p - get a char pointer version of p (a)
a + 1 - add one to it (b)
(int*)b - cast it back to an int pointer (c)
p = c - replace p with that value
Below is a piece of code copied from a website.
The value set for the direction prints the respective character from "nsew". For example the output of this code is character w.
I am wondering how does it work.
#include<stdio.h>
void main (void){
int direction = 3;
char direction_name = direction["nsew"];
printf("%c",direction_name);
}
This is because the array subscript operator is commutative, i.e., this:
const char *p = "Hello";
char x = p[0];
Is equivalent to
const char *p = "Hello";
char x = 0[p];
Weird, huh? In your case you are indexing into the third position of the string literal (which is an array) "nsew".
some_ptr[n] is equivalent to *(some_ptr + n), and since addition is commutative, it is also equivalent to *(n + some_ptr). It then follows that n[some_ptr] is also an equivalent expression.
I wouldn't recommend using this "feature" however... seriously, don't do it.
Operator [] has the same semantics as pointer arithmetics. So a[i] is equivalent to *(a + i) which is equivalent to *(i + a) which is equivalent to i[a]:
So direction["nsew"] == "nsew"[direction] == "nsew"[3] == 'w'
So I have the following code snippet:
#include <stdio.h>
void pointer_shift(int *a, int n);
int main(void) {
int a[] = {100, 101, 102};
pointer_shift(a1, 3);
}
void pointer_shift(int *a, int n) {
int i;
for (i = 0; i != n - 1; i++) {
*(a + i) = *(a + i + 1);
}
}
I just want to clarify how the pointers work in this snippet. So pointer_shift takes in 'a', a pointer to an int, correct? a1 is passed in to this parameter, and since arrays decay to a pointer to their first element, it works.
First of all, hopefully what I said in the above paragraph is correct. Secondly, what does *(a + i) = *(a + i + 1); actually do? Say we're on the first iteration of the for loop, and i = 0. Then the left side, *a, accesses what, exactly? Does it represent a pointer? I thought * was the dereferencing operator, and accesses the object that a pointer points to... And so then it sets *a = *(a + 1). (a + 1) is the next element in the array, but what exactly does this assignment do, and why?
Thanks!
It is actually not pointer shift, but value shift, *(a+i) is of same effect as a[i], so what it does is a[i] = a[i+1]
*(a + i) = *(a + i + 1); is copying array elements within the array using a bit of pointer arithmetic.
*(a + i) is equivalent to a[i], so the statement is equivalent to a[i] = a[i + 1];. The loop is moving the array values "to the left" in the array: a[0] = a[1]; a[1] = a[2]; and so on.
Your understanding of the function call is correct.
I just want to clarify how the pointers work in this snippet. So pointer_shift takes in 'a', a pointer to an int, correct? a1 is passed in to this parameter, and since arrays decay to a pointer to their first element, it works.
Yes, when you pass an array to a function it degrades to a pointer. An array is not a pointer in an object sense, but it is a pointer in a value sense. When you pass it to a function its value is passed, i.e., a pointer to the first element.
array indexing is the same as pointer arithmetic, so the last two lines in this snippet are equivalent:
int arr[] = {1, 2, 3};
arr[0] = 10;
*arr = 10;
as are these:
arr[1] = 20;
*(arr + 1) = 20;
The expression a + i is pointer arithmetic, incrementing the memory address stored in a by i units of the pointer size of a. So if a pointer to an int takes four bytes on your system, and if the current memory address is, say, 0x1234 the value of a + 1 would be 0x1238.
What the asterisk does is dereference that address and access the actual value at that address. If you have 100 stored at a or a[0], and 101 stored at a + 1 or a[1], then *(a + i) = *(a + i + 1) replaces 100 with 101 at a[0], for i = 0.
Basically, you want to read this C tutorial on pointers and arrays.
I have a piece of code written in C where some pointer arithmetic is performed. I would like to know how the output comes to be this?
#include <stdio.h>
int main()
{
char arr[] = "gookmforgookm";
char *ptr1 = arr;
char *ptr2 = ptr1 + 3;
printf ("ptr2 - ptr1 = %d\n", ptr2 - ptr1);
printf ("(int*)ptr2 - (int*) ptr1 = %d", (int*)ptr2 - (int*)ptr1);
getchar();
return 0;
}
Output is below:
ptr2 - ptr1 = 3
(int*)ptr2 - (int*) ptr1 = 0
Strictly speaking, you're invoking undefined behaviour and any result that the program produces is OK according to the C standard.
However, you're probably on a machine where sizeof(int) == 4 (as opposed to say, 2). Since there are 4 bytes to an integer, two addresses which are 3 bytes apart are part of the same integer, so the difference between the addresses is 0 * sizeof(int). You might find a different answer if you chose ptr1 = arr + 1;, or you might not. But that's the beauty of undefined behaviour - it would be 'right' either way.
After the subtraction you need to divide the result in the size of the pointed type.
(int*)ptr2 - (int*)ptr1 == (0x1000003 - 0x1000000) / sizeof(int)
(int*)ptr2 - (int*)ptr1 == (0x1000003 - 0x1000000) / 4 == 0
ptr1 and ptr2 are both char * type, that means one byte one pointer.
char *ptr2 = ptr1 + 3;
so
ptr2 - ptr1 = 3
Next, you cast both pointer to type int *, int type need 4 byte, so both pointer aim at the same int, both pointer have the same value through the memory align, you get the 0 result.
When you subtract two pointers, as long as they point into the same array, the result is the number of elements separating them.
Pointer Subtraction and Comparison
The memory addresses of the elements of the same array are always sequential. i.e
if the memory adress of myarray[0] is:
0x4000000
then the memory address of myarray[2] will definitely be
0x4000002
So when you store the address of arr into ptr1 assume it to be x
, and then when you make the address of ptr2, three units higher than ptr1, it will be x+3. So when you subtract ptr1 from ptr2 the answer will be:
(x+3) - x = 3
Hence the answer.
In the second printf() statement, if you want it to display the same result as above (3), you have to convert the pointer to int and not int*.
char *myvar; // given contents somewhere
int addr = (int)myvar; // addr now = the char pointer
So In your case:
printf ("(int)ptr2 - (int) ptr1 = %d", (int)ptr2 - (int)ptr1);
This is an example of what my code looks like:
void *a = NULL;
void *b = //something;
a = (void *)(*((char *)b + 4));
The value that (b+4) is pointing to is an address that I want to store in a. When I try to compile, I get "warning: cast to pointer from integer of different size." What does this mean, and what should I do to fix it?
EDIT: To clarify, I don't want 'a' to point to an address that is 4 bytes greater than 'b'. In my program, I know that the value stored at ((char *)b + 4) is itself another pointer, and I want to store this pointer in 'a'.
This is a char*:
(char *)b + 4
That means that this:
*((char *)b + 4)
is a char. Then you proceed to cast that char to a void* and the compiler complains. You don't have to manually cast to void* in C so just this should do:
a = (char *)b + 4;
Update for comments: Sounds like you're after this:
a = *(char **)((char *)b + 4)
it would improve the readability, if you wrote the statements apart
I did this for you and get:
char *c = (char *)b;
char *d = c + 4;
a = (void *)
(*d); // <- this is c char and you want to cast it to a pointer
seems like you wrote an asterisk too much
What it sounds like: something is wrong in your pointers.
In this case, re-examine your expression: is that really the address of a char you're getting?
(void *)(*((char *)b + 4));
so
(char *)b
is a pointer to char, as is
(char *)b+4
but then *((char *)b+4) is dereferencing (char *)b+4, so that's type char -- and you're then trying to cast that thing, which is probably 1 byte, into a 4 or 8 byte address. Ergo, mismatched sizes.
void *a = NULL;
char jig[10]="jigarkumar";
void *b = jig;
printf("b is %p",b);
a = (void *)(((char *)b + 4));
printf("\na is %p",a);
problem is here
a = (void *)(*((char *)b + 4));
^
|
this * fetch the value stored at b+4 address & it is assigned to a which is wrong
so just remove that & your code will work fine