Casting pointers for arithmetic - C - c

If I have a void * x, but I want to cast it to a char *, so that the ++ operator will make it point to the next byte and not the next 4 byte block.
However, when I do:
(char *) x -= byte_length;
The compiler complains:
Error, lvalue required as left value of assignment.
Where am I going wrong please?
Thanks.

I would do it like this:
x = (char*)x - byte_length;
Cast x to char*, then apply the offset, then assign back to x. Since void* is assignment compatible with all pointer types no further cast is needed.

(char *)x evaluates to a temporary with the same value as x but a different type. The compiler won't allow -= on a temporary. Do
x = (char *)x - byte_length;
The situation is analogous to the following:
short x = 0;
(long)x += 1; // invalid; (long)x is a temporary
x = (long)x + 1; // works

Do something like this:
void* x;
char* cx = (char*)x;
cx -= byte_length;
x = cx;

(char*) x -= byte_length;
In this statement, (char*) x creates a temporary value with char* as type. You can only assign to variables, or more precisely, references (or an lvalue according to your compiler).
One way to get a reference to it is casting the address of x to char* and dereferencing that:
*(char*) &x -= byte_length;

(char*)x is a temporary value that has not address in memory. You can't do a -- to it, for the same reason that if you have int i, you can't do (i+5)++.
You should do x=(char*)x-byte_length; instead.
See also http://c-faq.com/ptrs/castincr.html

Related

What does *p mean when **p is already declared

Code
short **p = (short **)malloc(sizeof(short *));
*p = malloc(sizeof(short));
**p = 10;
printf("**p = %d", **p);
Output
**p = 10
In this code, a multiple pointer **p is declared and *p is used without any declaration(maybe it's by **p).
What does *p mean in my case? Sorry for very simple question.
I saw C standard and stack overflow, but I couldn't find out something.
For any array or pointer p and index i, the expression p[i] is exactly equal to *(p + i) (where * is the unary dereference operator, the result of it on a pointer is the value that the pointer is pointing to).
So if we have p[0] that's then exactly equal to *(p + 0), which is equal to *(p) which is equal to *p. Going backwards from that, *p is equal to p[0].
So
*p = malloc(sizeof(short));
is equal to
p[0] = malloc(sizeof(short));
And
**p = 10;
is equal to
p[0][0] = 10;
(**p is equal to *(*(p + 0) + 0) which is equal to *(p[0] + 0) which is then equal to p[0][0])
It's important to note that the asterisk * can mean different things in different contexts.
It can be used when declaring a variable, and then it means "declare as pointer":
int *p; // Declare p as a pointer to an int value
It can be used to dereference a pointer, to get the value the pointer is pointing to:
*p = 0; // Equal to p[0] = 0
And it can be used as the multiplication operator:
r = a * b; // Multiply the values in a and b, store the resulting value in r
short **p = (short **)malloc(sizeof(short *));
This line declares a pointer to a pointer p. Additionally the value of p is set to the return value from malloc. It is equivalent to
short **p;
p = (short **)malloc(sizeof(short *));
The second line
*p = malloc(sizeof(short));
Here *p is the value of p. *p is of type pointer. *p is set to the return value of malloc. It is equivalent to
p[0] = malloc(sizeof(short));
The third line
**p = 10;
**p is the value of the value of p. It is of type short. It is equivalent to
p[0][0] = 10
In effect what the code above does is to allocate a 2D array of short, then allocate memory for the first row, and then set the element p[0][0] to 10.
As a general comment on your code, you should not use typecast in malloc. See Do I cast the result of malloc?
What does *p mean when **p is already declared?
short **p = (short **)malloc(sizeof(short *));
(better written as)
short **p = malloc (sizeof *p);
Declares the pointer-to-pointer-to short p and allocates storage for a signle pointer with malloc and assigns the beginning address for that block of memory to p. See: In C, there is no need to cast the return of malloc, it is unnecessary. See: Do I cast the result of malloc?
*p = malloc(sizeof(short));
(equivalent to)
p[0] = malloc (sizeof *p[0]);
Allocates storage for a single short and assigns the starting address for that block of memory to p[0].
**p = 10;
(equivalent to)
*p[0] = 10;
(or)
p[0][0] = 10;
Assigns the value 10 to the dereference pointer *p[0] (or **p or p[0][0]) updating the value at that memory address to 10.
printf("**p = %d", **p);
Prints the value stored in the block of memory pointed to by p[0] (the value accessed by dereferencing the pointer as *p[0] or **p)
The way to keep this straight in your head, is p is a single pointer of type pointer-to-pointer-to short. There are 2-level of indirection (e.g. pointer-to-pointer). To remove one level of indirection, you use the unary * operator, e.g.
*p /* has type pointer-to short */
or the [..] also acts as a dereference such that:
p[0] /* also has type pointer-to short */
You still have a pointer-to so you must remove one more level of indirection to refernce the value stored at the memory location pointed to by the pointer. (e.g. the pointer holds the address where the short is stored as its value). So you need:
**p /* has type short */
and
*p[0] /* also has type short */
as would
p[0][0] /* also has type short */
The other piece to keep straight is the type controls pointer-arithmetic. So p++ adds 8-bytes to the pointer-to-ponter address so it now points to the next pointer. If you do short *q = (*p)++; (or short *q = p[0]++, adds 2-bytes to the address for the pointer-to-short, soqnow points to the nextshortin the block of memory beginning at*p(orp[0]`). (there is no 2nd short because you only allocated 1 -- but you get the point)
Let me know if you have further questions.
Let me put it in different way,
consider an example,
int x;
int *y = &x;
int **z = &y;
x = 10;
Which simplifies to this,
Note: Only for illustration purpose I have chosen address of x,y,z as 0x1000,0x2000,0x3000 respectively.
What does *p mean in my case?
In short the snippetshort **p = (short **)malloc(sizeof(short *)); is dynamically allocating a pointer to a pointer of type short i.e same asy in my example.

Void* arithmetic and type casting

I have tried to understand void* recently by testing a few things, here is the test code:
#include <stdio.h>
int main(int argc, char** argv)
{
float nb2 = 2.2;
void* multi_type_ptr = &nb2;
printf("\nmulti_type_ptr:\n");
printf("Elem 1: %f\n",*(float*)multi_type_ptr);
// *(multi_type_ptr + 1) = 4;
// *(int*)(multi_type_ptr + 1) = 4;
*((int*)multi_type_ptr + 1) = 4;
printf("Elem 2: %d\n",*((int*)multi_type_ptr + 1));
return 0;
}
Does this instruction can't work because the language/compiler don't know how much bytes it should add to the address of multi_type_ptr (it doesn't know the size of the type pointed by void*)?
*(multi_type_ptr + 1) = 4;
Also a void* cannot be dereferenced, so it should be cast to the right type, right? This line still can't work because of the issue mentioned above.
*(int*)(multi_type_ptr + 1) = 4;
Does this assignment works because the language/compiler understand it have to add (1 * sizeof int) to the address of multi_type_ptr? I use cl compiler included in Visual Studio.
*((int*)multi_type_ptr + 1) = 4;
It looks like the result of (multi_type_ptr + 1) is still an (int*) when its content is accessed by the * at the beginning of the line, am i right?
Thank you in advance for your future correction, explanation and reinforcement.
*(multi_type_ptr + 1) = 4;
The expression multi_type_ptr + 1 is not valid C because C does not allow pointer arithmetic with void *.
*((int*)multi_type_ptr + 1) = 4;
This statement compiles in your machine because (int*) multi_type_ptr + 1 does pointer arithmetic with int *. Nevertheless pointer addition in C is undefined behavior if the resulting pointer is not in the same array object as the operand (or one past the last element) and dereferencing the resulting pointer is undefined behavior if the resulting pointer is outside the array object, so in your case the * expression (and thus the statement) invokes undefined behavior.
There are several questions here:
Does this instruction can't work because the language/compiler dont know how much bytes it should add to the adress of multi_type_ptr (it doesn't know the size of the type pointed by void*)?
*(multi_type_ptr + 1) = 4;
Yes, you are right. Some compilers (GCC for example) allow pointer arithmetic with void pointers and treat them as if pointing to objects of size 1 (just like char*), to avoid the frequent cast from void* just to move around.
Does this assignment works bacause the language/compiler understand it have to add (1 * sizeof int) to the adress of multi_type_ptr? I use cl compiler included in Visual Studio.
*((int*)multi_type_ptr + 1) = 4;
Yes, right again. But note that while this code is syntactically correct, and it will compile, it is technically Undefined Behaviour for two reasons:
You are type punning or type aliasing the nb2 variable. That is you are accessing it using a different type than that defined (defined as float, used as int) (the exception would be that you are using char pointers, but that is not the case).
If 2*sizeof(int) > sizeof(float) (quite likely) then your pointer arithmetic is taking you outside of nb2 bounds, and you are probably corrupting your stack.
It looks like the result of (multi_type_ptr + 1) is still an (int*) when its content is accessed by the * at the begginning of the line, am i right?
No. Cast operator have high precedence, so this line:
*((int*)multi_type_ptr + 1) = 4;
is actually read as:
*(((int*)multi_type_ptr) + 1) = 4;
That is, like:
int *temp1 = (int*)multi_type_ptr);
int *temp2 = t1 + 1;
*temp2 = 4;
But again, beware the type aliasing!

C Putting code in one liner

I'm learning C and this is probably the most stupid question ever but here it goes!
My code:
char tmp = *x++;
char *g = &tmp;
Can I do this line of code in a one liner? With something like:
char *g = &(*x++);
More info:
char *x = "1234";
//Turn each 'number' to a int
while(*x != '\0'){
char tmp = *x++;
char *x = &tmp;
int t = atoi(x);
}
If x is a pointer to char (and points to an existing object), then the declaration char *g = &(*x++); is allowed in standard C and has defined behavior.
The result of the * operator is an lvalue, per C 2011 6.5.3.2 4, so its address may be taken with &.
In detail:
x++ increments x and produces the original value of x. (Note: Incrementing a pointer requires that the pointer point to an object. It does not require that it be an array element or that there be another object after it; you are allowed to increment to point one past an object, as long as you do not then dereference a pointer to a non-existent object.)
*x++ dereferences the pointer (the original value of x). The result is an lvalue.
&(*x++) takes the address of the lvalue, which is the original value of x.
Then this value is used to initialize g.
Additionally, C 2011 6.5.3.2 3 specifies that the combination of & and * cancel, except that the result is not an lvalue and the usual constraints apply, so the & and * operations are not actually evaluated. Thus, this statement is the same as char *g = x++;.
Just as a hint: Are you aware that you are shadowing the outer x variable?
What you are currently doing is:
char *x = "1234"; //declare c style string
while(*x != '\0'){ //for the conditional the "outer" x will be used for comparsion
char tmp = *x++; //increment x to point to whatever comes sizint atoi (const char * str);eof(char) bytes afterwards; dereference what x previously pointed to (postfix ++) and save it in local char tmp
char *x = &tmp; //take adress of the local char and save its adress in a new local/inner char*
int t = atoi(x); //call atoi on the inner x
Although this may work it may be confusing style to shadow variables like this. (Confusing for other developers especially)
Also take a look at the signature of atoi:
int atoi (const char * str);
Here you can see that you can safely pass the pointer like this:
int t = atoi(&x);
++x;
Or preferably:
int t = atoi(&x++);

Given the address of a pointer, how do I get what it points to?

If I am given the address of a pointer, how do I get what the pointer points to?
You might mean:
/**
* #param pointer_to_pointer_to_int: the address of a pointer to an integer.
**/
void function_that_takes_pointer_to_pointer(int **pointer_to_pointer_to_int) {
int the_int = **pointer_to_pointer_to_int;
printf("The pointer points to %d\n", the_int);
}
Assuming it is a valid pointer, you can dereference it using the unary * operator:
int *ptr = ...;
int x;
x = *ptr;
The unary * operator.
int *ptr = malloc(sizeof(int));
*ptr = 45;
printf("address: %p, value: %d", ptr, *ptr);
The most common way to be given the address of a pointer is through a pointer to a pointer. If the value the pointer points to is an integer, the type of the address of the pointer is int **.
To get the pointer to the integer, you need to dereference the double pointer. Then you can dereference the integer pointer to get the integer value.
To dereference a pointer, use the * operator.
int **double_pointer = given;
int *int_pointer = *double_pointer;
int value = *int_pointer;
You can also chain the dereferences to do that on one line.
int **double_pointer = given;
int value = **double_pointer;
The unary * operator returns or sets the value at a memory location.
For example:
int val = 42;
int* ptr = &val;
assert(val == *ptr);
If you have the address of a pointer, you would write **pointerpointer.
Going off of RedX's comment, If you have a situation like
void foo(void *ptr)
{
...
}
where the value of ptr is a pointer to a pointer to int, for example, you could do something like
void foo(void *ptr)
{
int x = **((int **) ptr);
...
}
Basically, you cast ptr to int **, then double-dereference it.
If you don't know what the target type is ahead of time (e.g., the function is meant to handle pointers to multiple types), then you're going to have to figure out a way to encode that type information in a second argument and pass it to the function.
There are two possible answers to your question depending on whether the compiler has a clue about the data that's referred or not.
Declaring a pointer of type int *, char * or mytype * instructs the compiler that a later attempt to dereference it using the unary * operator must yield a result of int, char or mytype respectively.
In the other case you would normally store a pointer either in a void * (generic, untyped pointer) or in a uintptr_t (an unsigned int the same size of a pointer, but without pointer semantics). In such a case the compiler doesn't have a clue how to interpret the dereferencing operator, so you must explicitly cast such a pointer to another pointer type, and only then dereference it:
int x = 5;
void *p = &x; /* p now points to an int, but the compiler doesn't know it */
printf("%d\n", *((int *) p)); /* we know what we did and don't rely on the compiler */
printf("%d\n", *p); /* compile-time error, dereferencing has undefined semantics */
Note that in compiled, unmanaged languages like C there is no runtime information about what kind of data a pointer is pointing to, unlike languages like Java where you can use the instanceof operator to check what a reference is really pointing to at runtime.

What is the correct way to offset a pointer?

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.

Resources