What is the correct way to offset a pointer? - c

I want to pass a pointer to a function. I want this pointer to point to some place in the middle of an array. Say I have an array like such unsigned char BufferData[5000];, would the following statement be correct syntactically?
writeSECTOR( destAddress, (char *)( BufferData + (int)(i * 512 )) );
// destAddress is of type unsigned long
// writeSECTOR prototype: int writeSECTOR ( unsigned long a, char * p );
// i is an int

That would do, but just make it:
writeSECTOR( destAddress, &BufferData[i * 512]);
(It sounds like writeSECTOR really should take an unsigned char* though)

Pointer arithmetic is fairly simple to understand. If you have a pointer to the first element of an array then p + 1 points to the second element and so on regardless of size of each element. So even if you had an array of ints, or an arbitrary structure MyData it would hold true.
MyData data[100];
MyData *p1 = data;; // same as &data[0]
MyData *p2 = p1 + 1; // same as &data[1]
MyData *p3 = p2 + 1; // same as &data[2]
MyData *p4 = p2 - 1; // same as &data[0] again
If your array is unsigned char then you just add however many bytes offset you wish to go into the array, e.g.
unsigned char data[16384];
unsigned char *offset = data + 512; // same as &data[512]
*offset = 5; // same as data[512] = 5;
Alternatively if the notation is confusing, you can always refer to it as it is shown in comments above, e.g. &data[512]

You can just do BufferData + i * 512. An arithmetic + operator on char* yields a char* when you add an integer value to it.

That should work. In C, adding an integer to a pointer increases the pointer by the integer multiplied by the sizeof the type the pointer points to.

it looks ok, but try it on the compiler,
You can use writeSECTOR( destAddress, &BufferData[i * 512] );

That looks like it will pass in the address of the i*512'th element of the array. Is that what you want it to do?
I don't really see what that cast to int is buying you though.

That should work as you think.
Pointer in C is just an address in RAM,so you could drift the pointer in your measure.

Related

How do you get the address of array elements given the address of the array itself in C?

*edited to clarify that the array is unknown
If the address of unknown integer array is 0x00006ffd29c78e70 (and an integer is 4 bytes), what is the address of element array[1]?
Many thanks in advance.
The address of the array is also the address of its first element. This is because the array itself in memory consists solely of each of its elements (starting at index 0) in turn. Therefore if A is an array, &A[0] points to the same memory as A. (Note that there is a technical difference between an array of integers type and a pointer to an integer type, though they are in many cases interchangeable as the former decays into the latter under certain circumstances which are beyond the scope of this question; this is why I described them as pointing both to the same memory).
You asked about the first element, and then referred to A[1]. Note that A[1] is the second element. A[0] is the first element.
So in your particular example, you could do:
int *A = (int *)0x00006ffd29c78e70;
int *A1 = &A[1]; // points to second element
int foo = *A1; // second element contents
or using pointer arithmetic
int *A = (int *)0x00006ffd29c78e70;
int *A1 = A+1; // points to second element
int foo = *A1; // second element contents
Note the +1 does not add one to the (byte) address, but increments the pointer by one int.
Note I have written int above - use the correct integer data type to represent your 4 byte integer.
If 0x00006ffd29c78e70 is the address of a valid array of ints then you can assign it to a pointer:
int *p = (int*)0x00006ffd29c78e70;
then p[1] will give you the next element (second) in that array.
Elements are at
unsigned char *addressofarray = whatever;
unsigned char *secondelement = addressofarray + sizeof arrayelement;
unsigned char *nthelement = addressofarray + n * sizeof arrayelement;
you just got a pointer to acess any thing in array as:
int *ptr = (int*) 0x00006ffd29c78e70;
you can acess any element as:
*(ptr+i) //i is the index

C Double Typecast

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

Dereferencing a casted void pointer and using post increment operator

I have a function
foo(void *buf) {
int i = 0;
unsigned char ptr = get_user_name();
//I want the buffer to hold user name from some position onwards
for(i=0;i<MESSAGE_LTH;i++)
*( (unsigned char*)(buf) + sizeof(some_struct)) ++ = ptr[i];
}
I am getting error: lvalue required as increment operand
I want the buffer to hold the username soon after the struct;
This:
unsigned char ptr = get_user_name();
seems like it should be:
const unsigned char *ptr = get_user_name();
It must be a pointer since you're accessing it like one. It should be const since you're only reading from it.
The copying should be done using memcpy(), and incrementing the pointer afterwards can be done separately:
unsigned char *put = buf; /* Proper type, for pointer arithmetic. */
put += sizeof(some_struct); /* Advance into the buffer. */
memcpy(put, ptr, MESSAGE_LTH); /* Do the copy. */
put += MESSAGE_LTH; /* Advance the pointer to after the name. */
Of course at the end of the above, it's hard to know what to do with put. Perhaps returning it out of the function would make sense, but you don't specify.
That line should be rewritten as
*( (unsigned char*)(buf) + sizeof(some_struct) + i) = ptr[i];
Indeed, an easier-to-understand implementation:
memcpy(buf + sizeof(some_struct), ptr, MESSAGE_LTH);
without the loop.

Multiplying what's pointed to by pointers

Pointer1 points to 5.
Pointer2 points to 3.
I want to multiply 5*3, but I only have the pointers. How would I do this in C?
Also, what does uint32_t *pointer mean when:
pointer[2] = {1, 2};
I do not know what is so hard for the answerers to understand about this question. It is obviously about dereferencing pointers.
This is how you display the contents of the pointer that it is pointing to:
#include <stdio.h>
int main(void)
{
int num1 = 5;
int num2 = 3;
int* num1_ptr = &num1;
int* num2_ptr - &num2;
int sum = *num1_ptr * *num2_ptr;
printf("%d\n", sum);
return 0;
}
*num1_ptr and *num2_ptr takes your pointers and references what the contents of that memory address.
I can't answer the first half of your question without more information, but uint32_t* pointer is simply a pointer to an unsigned 32-bit integer value (unsigned int and uint32_t are usually equivalent types, depending on your compiler).
If I see a declaration that simply reads uint32_t* pointer without more information I'm going to assume it's a pointer to a single value, and that using the indexing operator [n] on such a pointer is basically overflowing the single-element-sized buffer. However if the pointer is assigned the result from an array or buffer function (e.g. malloc, calloc, etc) then using the indexing operator is fine, however I would prefer to see uint32_t pointer[] used as the declaration as it makes it much easier to determine the developer's intent.
uint32_t *pointer is just a pointer with garbage value unless you point it to something.
pointer[0] = 1;
pointer[1] = 2;
is only valid if you have earlier pointed it to some array of type uint32_t with atleast size two or to a block containing uint32_ts defined using malloc as follows:
uint32_t *pointer;
pointer = (uint32_t*)malloc(sizeof(int*SIZE); //SIZE > 2 here
or
uint32_t array[10];
pointer = & array[0]; // also, pointer = array; would also work.
int main(void)
{
int variableA = 5;
int variableB = 3;
int* ptr1 = &variableA; // Pointer1 points to 5.
int* ptr2 = &variableB; // Pointer2 points to 3.
int answer;
answer = (*ptr1) * (*ptr2); // I want to multiply 5*3, but I only have the pointers.
// Answer gets set to [value stored at ptr1(5)] MultipliedBy [value stored at ptr2(3)]
}
Your misconception is that pointers do not refer to values, such as 5 and 3.
pointers refer to variables, such as variableA and variableB; those variables have values which can be accessed and changed via the pointer.But the pointer only refers to the variable, not directly to the value behind it.

Understanding C: Pointers and Structs

I'm trying to better understand c, and I'm having a hard time understanding where I use the * and & characters. And just struct's in general. Here's a bit of code:
void word_not(lc3_word_t *R, lc3_word_t A) {
int *ptr;
*ptr = &R;
&ptr[0] = 1;
printf("this is R at spot 0: %d", ptr[0]);
}
lc3_word_t is a struct defined like this:
struct lc3_word_t__ {
BIT b15;
BIT b14;
BIT b13;
BIT b12;
BIT b11;
BIT b10;
BIT b9;
BIT b8;
BIT b7;
BIT b6;
BIT b5;
BIT b4;
BIT b3;
BIT b2;
BIT b1;
BIT b0;
};
This code doesn't do anything, it compiles but once I run it I get a "Segmentation fault" error. I'm just trying to understand how to read and write to a struct and using pointers. Thanks :)
New Code:
void word_not(lc3_word_t *R, lc3_word_t A) {
int* ptr;
ptr = &R;
ptr->b0 = 1;
printf("this is: %d", ptr->b0);
}
Here's a quick rundown of pointers (as I use them, at least):
int i;
int* p; //I declare pointers with the asterisk next to the type, not the name;
//it's not conventional, but int* seems like the full data type to me.
i = 17; //i now holds the value 17 (obviously)
p = &i; //p now holds the address of i (&x gives you the address of x)
*p = 3; //the thing pointed to by p (in our case, i) now holds the value 3
//the *x operator is sort of the reverse of the &x operator
printf("%i\n", i); //this will print 3, cause we changed the value of i (via *p)
And paired with structs:
typedef struct
{
unsigned char a;
unsigned char r;
unsigned char g;
unsigned char b;
} Color;
Color c;
Color* p;
p = &c; //just like the last code
p->g = 255; //set the 'g' member of the struct to 255
//this works because the compiler knows that Color* p points to a Color
//note that we don't use p[x] to get at the members - that's for arrays
And finally, with arrays:
int a[] = {1, 2, 7, 4};
int* p;
p = a; //note the lack of the & (address of) operator
//we don't need it, as arrays behave like pointers internally
//alternatively, "p = &a[0];" would have given the same result
p[2] = 3; //set that seven back to what it should be
//note the lack of the * (dereference) operator
//we don't need it, as the [] operator dereferences for us
//alternatively, we could have used "*(p+2) = 3;"
Hope this clears some things up - and don't hesitate to ask for more details if there's anything I've left out. Cheers!
I think you are looking for a general tutorial on C (of which there are many). Just check google. The following site has good info that will explain your questions better.
http://www.cplusplus.com/doc/tutorial/pointers/
http://www.cplusplus.com/doc/tutorial/structures/
They will help you with basic syntax and understanding what the operators are and how they work. Note that the site is C++ but the basics are the same in C.
First of all, your second line should be giving you some sort of warning about converting a pointer into an int. The third line I'm surprised compiles at all. Compile at your highest warning level, and heed the warnings.
The * does different things depending on whether it is in a declaration or an expression. In a declaration (like int *ptr or lc3_word_t *R) it just means "this is a pointer."
In an expression (like *ptr = &R) it means to dereference the pointer, which is basically to use the pointed-to value like a regular variable.
The & means "take the address of this." If something is not a pointer, you use it to turn it into a pointer. If something is already a pointer (like R or ptr in your function), you don't need to take the address of it again.
int *ptr;
*ptr = &R;
Here ptr is not initialized. It can point to whatever. Then you dereference it with * and assign it the address of R. That should not compile since &R is of type lc3_word_t** (pointer to pointer), while *ptr is of type int.
&ptr[0] = 1; is not legal either. Here you take the address of ptr[0] and try to assign it 1. This is also illegal since it is an rvalue, but you can think of it that you cannot change the location of the variable ptr[0] since what you're essentially trying to do is changing the address of ptr[0].
Let's step through the code.
First you declare a pointer to int: int *ptr. By the way I like to write it like this int* ptr (with * next to int instead of ptr) to remind myself that pointer is part of the type, i.e. the type of ptr is pointer to int.
Next you assign the value pointed to by ptr to the address of R. * dereferences the pointer (gets the value pointed to) and & gives the address. This is your problem. You've mixed up the types. Assigning the address of R (lc3_word_t**) to *ptr (int) won't work.
Next is &ptr[0] = 1;. This doesn't make a whole lot of sense either. &ptr[0] is the address of the first element of ptr (as an array). I'm guessing you want just the value at the first address, that is ptr[0] or *ptr.

Resources