Change the address of a pointer - c

I have an Array of integers called bufferA[] and a pointer *ptr which points to the first integer in this Array bufferA[0]. Now, i would like to Change the pointer to point to the second value bufferA[1]. As i debbug the Code i can see that the address of the first integer in this Array is 0x1702 and now i would like to Change the pointer so it Points to 0x1704 which is the address of bufferA[1].
There is probably some way to make this without the pointer and just read the values of the Array, but this Array is passed from the ADC-module to the DMA-module and instead of just taking the Arrays (which makes storing them in the DMA useless) i would like to just take the address of the first value and change it up to read the following values.
i hope this somehow explains my Problem...

How about ptr = ptr + 1;? (Or equivalently in this context ptr += 1; or ptr++; or ++ptr;?) The C compiler knows how many bytes are taken up by the item that ptr points to, because of its declared type, and will automatically increment the pointer by the right number of bytes.

Arrays in C are always passed by reference, there is no copy operation of you pass it as an argument to a function! (This is a first gotcha of beginner C programmers)
Read something about pointers in C, first, but in short:
int a = 5; // declares a integer-type of value 5
int* pta; // declares a pointer-to-integer type
pta = &a // assigns the **address** of a to pta (e.g. 0x01)
int b = *pta // assingns the **value** of the address location that pta is pointing to into b
// (i.e. the contents of memory address 0x01, which is 5)
*pta = 4 // assigns 4 to the content of the memory address that pta is pointing to.
// now b is 5, because we assigned the value of the address that pta was pointing to
// and a is 4, because we changed the value of the address that pta was pointing to
// - which was the address where variable a was stored
The variable bufferA is itself a pointer to the address of the first element. bufferA + 1 gives you the address of the second element, because arrays are stored in memory sequentially.
Or if you want a more readable format:
&bufferA[0] is the same as bufferA (address of the first element(e.g 0x11)
&bufferA[1] is the same as bufferA + 1 (address of the second element(e.g 0x12)
buffer[2] is the same as *(buffer + 2) (value at the address of the third element)

Related

Type casting the character pointer

I am from Java back ground.I am learning C in which i gone through a code snippet for type conversion from int to char.
int a=5;
int *p;
p=&a;
char *a0;
a0=(char* )p;
My question is that , why we use (char *)p instead of (char)p.
We are only casting the 4 byte memory(Integer) to 1 byte(Character) and not the value related to it
You need to consider pointers as variable that contains addresses. Their sole purpose is to show you where to look in the memory.
so consider this:
int a = 65;
void* addr = &a;
now the 'addr' contains the address of the the memory where 'a' is located
what you do with it is up to you.
here I decided to "see" that part of the memory as an ASCII character that you could print to display the character 'A'
char* car_A = (char*)addr;
putchar(*car_A); // print: A (ASCII code for 'A' is 65)
if instead you decide to do what you suggested:
char* a0 = (char)addr;
The left part of the assignment (char)addr will cast a pointer 'addr' (likely to be 4 or 8 bytes) to a char (1 byte)
The right part of the assignment, the truncated address, will be assigned as the address of the pointer 'a0'
If you don't see why it doesn't make sense let me clarify with a concrete example
Say the address of 'a' is 0x002F4A0E (assuming pointers are stored on 4 bytes) then
'*addr' is equal to 65
'addr' is equal to 0x002F4A0E
When casting it like so (char)addr this become equal to 0x0E.
So the line
char* a0 = (char)addr;
become
char* a0 = 0x0E
So 'a0' will end up pointing to the address 0x0000000E and we don't know what is in this location.
I hope this clarify your problem
First of all, p is not necessarily 4 bytes since it's architecture-dependent. Second, p is a pointer to an integer, a0 is a pointer to a character, not a character. You're taking a pointer pointing to an integer and casting it to a pointer to a character. There are few good reasons to do this. You could also cast the value to a character, but I can't imagine any reason for doing this either.
Pointers do not provide information whether they point to a single object of first object of an array.
Consider
int *p;
int a[5] = { 1, 2, 3, 4, 5 };
int x = 1;
p = a;
p = &x;
So having a value in the pointer p you can not say whether the value is the address of the first element of the array a or it is the address of the single object x.
It is your responsibility to interpret the address correctly.
In this expression-statement
a0=(char* )p;
the address of the extent of memory pointed to by the pointer p and occupied by an object of the type int (it is unknown whether it is a single object or the first object of an array) is interpreted as an address of an extent of memory occupied by an object of the type char. Whether it is a single object of the type char or the first object of a character array with the size equal to sizeof( int ) depends on your intention that is how you are going to deal with the pointer.

Stack vs. heap pointers in C

I'm currently learning C and I'm confused about memory layout and pointers.
In the following code, it is my understanding that the array is allocated on the stack.
#include <stdio.h>
int main () {
int x[4];
x[0] = 3; x[1] = 2; x[2] = 1;
printf("%p\n",x);
printf("%p\n", &x);
}
My question is, why do the two print calls output the same value?
I tried a similar snippet using malloc (allocate on the heap), and the values differ.
#include <stdio.h>
#include <stdlib.h>
int main () {
int *x = malloc(sizeof(int) * 4);
x[0] = 3; x[1] = 2; x[2] = 1;
printf("%p\n",x);
printf("%p\n", &x);
}
The reason is that unlike you were probably taught, arrays are not pointers. Arrays in C decay into pointers1 under some circumstances. When you pass an array to a function, it decays into a pointer to the first element. The address of that element is the same as the address of the entire array (an address is always to the first byte of an object).
What you get from malloc is not an array, but the address of a chunk of memory. You assign the address to a pointer. But the pointer and the chunk are separate entities. So printing the value of the pointer, as opposed to its address, yields different results.
(1) Decay is a fancy term for a type of implicit type conversion. When an array expression is used in most places (such as being passed as an argument to a function that expects a pointer), it automatically turns into a pointer to its first element. The "decay" is because you lose type information, i.e. the array size.
Your two print calls print the same value because one tries to print the array, which decays to a pointer to the array, and the other prints the address of the array. A pointer to the array contains the address of the array, so they're the same value.
In the second case, one prints the value of x, the other prints the address of x. Since x is a pointer to the block of memory you allocated, these must be different values.
So in the first case, all you have is an array (x). In the second case, you have an allocated block of memory (unnamed) and a pointer to that allocated block (x).
It is perhaps surprising that one can indeed take the address of a whole array, partly because one doesn't need to very often. The array in a sense is a single object, which has one address, which is the address of its first byte. Like with all objects, the address is obtained with the address operator, &.
The first element of an array (like all of its elements) has an address, too, which is the address of its first byte. A pointer to its first element is what the array type is "adjusted" to when it is passed as an argument to a function.
These two bytes are identical, and have the same address. But they have different types, which becomes obvious if you add 1 to them and print them again.
The pointer y, by contrast, is its own distinct object (probably 4 or 8 bytes in size; enough to store an address in it). Like any object it has an address which can be obtained with the & operator. Perhaps confusingly, it also contains an address, in this case the address of the first byte of the array. The two are of course not equal: The pointer object resides at a different location than the array (namely next to it on the stack, even if Olaf doesn't like that).
Minor remark: You use %p for printing pointers, which is good. If you do that, you should strictly spoken cast the pointer which you print to a void pointer: printf("%p\n", (void *)x);.

Understand pointers in C

I'm reviewing my C skills, and I'm struggling to understand some bits.
Here's my understanding of C and pointers.
Every time I declare a variable, C stores the value in memory.
int num = 12; // The 12 is stored somewhere in memory, let's say has address 0x54
To get the memory address of variable "num" we do:
printf("%p", &num); // this returns the 0x54
if I want to create a pointer, that points to the same value of "num", I do:
int *ptr = &num; // create a pointer and point him to 0x54
If I check both address:
printf("%p\n", &num); // prints 0x54
printf("%p\n", ptr); // prints 0x54
printf("%p\n", &ptr); // prints 0x94 is the address of the pointer itself
After the above...
I don't understand the output of my program.
I'm reading this book, and the author says that we can treat pointers as arrays and vice versa (except in some cases [if I understood correctly]).
int ages[] = { 23, 43, 12, 89, 2 };
printf("1-%d\n", ages[0]);
printf("1-%d\n", ages[1]);
printf("2-%p\n", &ages[0]);
printf("2-%p\n", ages);
printf("2-%p\n", &ages);
printf("3-%d\n", *(&ages[1]));
printf("4-%p\n", *(&ages));
printf("5-%p\n", &ages[1]);
printf("6-%p\n", &ages+1);
printf("7-%d\n", *(*(&ages)+1));
printf("8-%ld\n", sizeof(1));
Output with questions in comments:
1-23 // value of position 0, OK
1-43 // value of position 1, OK
2-0x7fff1fd500f0 // adress of the beginning of array, OK
2-0x7fff1fd500f0 // same as above, OK
2-0x7fff1fd500f0 // because ages is not a pointer, same as above, OK
3-43 // get address of ages, advance 4 bytes and then give me the value that is in that address, OK
4-0x7fff1fd500f0 // give me the address of ages, and then give the value that is in that address. The address I have in the print number 2, why doesn't return the value and show me the address? **NOT OK**
5-0x7fff1fd500f4 // give me the address of the position 1 of the array, the address that contains the number 43, OK
6-0x7fff1fd50104 // why I don't get the same number of the print 5? How I jump from f0 to 104? **NOT OK**
7-43 // why I need pointer of pointer, **NOT OK**
8-4 // this was just trying to understand print 6, OK
Can someone explain me prints 4, 6 and 7, and let me know if I'm thinking correctly on the other prints.
Your confusions all boil down to two things: how operator precedence works and what &ages means.
Let's look at the latter first. Obviously &ages is a pointer. But what is it a pointer to? It's not a pointer to int. Instead, it's a pointer to the type int[5].
So let's look at this:
printf("4-%p\n", *(&ages));
If you have a pointer to int[5], and you use * on it, you get what it points to: int[5]. This then decays to a pointer when being passed to printf. Specifically, a pointer to the first element of the array.
This:
printf("5-%p\n", &ages[1]);
Is a matter of operator precedence. Using explicit parenthesis, this is &(ages[1]); [] has higher precedence than &. Well, we know that ages[1] is the second int in the array. Using & on it will return a pointer to the second element in the array.
In a similar way:
printf("6-%p\n", &ages+1);
Operator precedence tells us that this is really (&ages) + 1. And remember, what is &ages? That's right, a pointer to int[5].
When we perform pointer arithmetic, we add the size of the object being pointed to to the address. That object is int[5], whose size is 20. Or in hex, 0x14. Therefore, you get an address 0x14 bytes from the start of the array.
As for:
printf("7-%d\n", *(*(&ages)+1));
Operator precedence tells us that this expression is really *((*(&ages)) + 1). So you get a pointer to int[5], turn it back into an int[5], then add 1 to it. That requires decaying the int[5] into an int*, then using pointer arithmetic. Then you access the value at that address.
A pointer is not just an address, it's an address with an associated type, which has a size.
Thus when you increment a pointer to array type, it skips the whole array.
Another issue in the code is array decay, where an expression that denotes an array, such as a or *&a, decays to a pointer to the first item of the array.
It's an unfortunate implicit conversion that made sense at the time of early C.
In C++ it causes much trouble.
arrays are too much efficient but the overhead of an array is the size which cannot be changed at runtime.
pointer is a variable of some type which has its address and type of data it points to eg:
//int* iPtr = 7; error pointers stores addresses not values
int* iPtr = 0x00000000 //(NULL) points to this address (correct);
above a pointer points to an integer is initialized to point to 0x00000000 which is NULL
int a = 7;
int* iPtr = &a;
cout << "a: " << a << endl; // printing value of a; result is a: 7
cout << "&a: " << &a << endl; // printing address of a: result is: &a: 0x0018FF44
cout << "iPtr: " << iPtr << endl; // printing the address iPtr points to as you guess it is the address of a so the result: iPtr: 0x0018FF44
cout << "*iPtr: " << *iPtr << endl; // printing the value stored in the address the iPtr points to so the result is as you guess: *iPtr: 7
the powerful use of pointers: they are too much flexible but dangerous they can point to an array, variable, changing the address, size at runtime...
they are used by linked-list, oop (polymorphism...)
*** don't mess with pointers
For #4, it's likely the result of compiler optimization. Taking the address and then immediately dereferencing the resulting pointer is effectively a no-op, so the optimizer's likely simply eliding those operations leaving just ages as the argument and that's the value you're seeing.
For #6, you're finding the address of the ages array and adding 1 to it, which in pointer arithmetic means "add 1 * the size of the variable pointed at". A 5-element array, assuming 4-byte integers, is 20 bytes long and if you check 0x7FFF1FD500F0 + 0x14 you get the result 0x7FFF1FD50104 that you see.
An array isn't a pointer, exactly. It acts a lot like one, but &(ages) isn't identical to &(ages[0]). Both have the same apparent value, but the former is a pointer to a 4-byte integer and the latter is a pointer to a 20-byte array of 4-byte integers. You have to keep that in mind when working with pointers to array elements, remembering to take the address of an element when you want to work within the array and need eg. the address of element 0 of the array and not the address of the array itself.

Why am I able to dereference and modify an `int * const` pointer? [duplicate]

This question already has answers here:
const usage with pointers in C
(6 answers)
Closed 7 years ago.
I know that a pointer have an address and content cell which holds an address.
So what happen to the pointer in the following code:
int a=5;
int* const ptr=&a;
*ptr=6;
The address ptr holds is not changed, so how can the value that ptr points to be changed?
int *const ptr = &a;
Here ptr is a constant pointer so you can't modify the location to which this pointer points to. But you can change the value stored in the location the pointer is pointing to.
So
*ptr = 6;
will modify the value of the variable a to 6.
What is not allowed is along with the existing code say you have
int b=5;
and you do
ptr = &b;
Then you are bound to get a error saying the constant pointer is being made to point to some other memory location.
If you go to a library and ask for a catalog then using the catalog find a book and then go and replace the book with a different one the catalog will still list the old book in it.
Similar thing happens in your code - the pointer (the reference itself) doesn't change, but what it points to does change.
If you meant to make the object that it points to be const then you need to declare it as such:
const int* ptr = &a;
or, to make both the object and the pointer const:
const int* const ptr = &a;
The value can change because what you are making constant is what the pointer points to, not what's inside of it.
Let me give you a way to think about it that is a good illustration but not meant to be literal. A pointer type could be viewed as an unsigned integer value (likely 32 or 64 bits in length, but that doesn't matter right now). In reality, all that's ever being stored into a pointer is an unsigned integer or Nil, which for our purposes we will call "zero".
When you define a pointer to be a constant in this way, you doing what this normally means; the content of this variable is constant. So the number that gets stuffed into this unsigned integer will not change.
However, when pointers are used (or dereferenced) they are special in that the value of the pointer is used to reference another memory location. That location is just another variable. Since your assignment does not change the actual pointer itself, it is completely valid. :)
Here the pointer ptr is of constant type. Constant pointer cannot change the address once it is loaded with an address.
In the third line *ptr=6; you are assigning the value to the address stored in the ptr pointer.ie.to a. So only the value of a changes to 6.
To change the address of ptr remove the keyword const and assign a address like ptr=&b
There is a 4-Byte area in memory, let's say at address 0x2000, this area is called "a"
With the instruction a=5the compiler (or better startup-code) fills this memory area with the 4-Byte integer 0x00000005 (which is 5 in decimal).
now another variable ptr is filled with the address of a: ptr = 0x2000.
The pointer contains the address of memory area a we say ptr points to a
*ptr means: the memory area ptrpoints to, in this case memory at 0x2000.
So finally *ptr=6 means that the integer/value 6 is filled into the memory area ptr points to.
Now the memory area at 0x2000 will contain 0x00000006 (decimal 6)
Edit
The modifier const in int* const ptrmeans that the actual value i.e. the adress in ptr will never change during the execution of the program, it will always point to / contain 0x2000.
This means that an assignment like
ptr = &b;
will fail with a compiler error message.
Here pointer is a constant type, Using that pointer you can only point the single memory address. now you can't point the another address using this pointer
int a,c;
int *const b=&a;
and when we are assign like this, it is through the error
b=&c;

Incrementing pointer to array

I came across this program on HSW:
int *p;
int i;
p = (int *)malloc(sizeof(int[10]));
for (i=0; i<10; i++)
*(p+i) = 0;
free(p);
I don't understand the loop fully.
Assuming the memory is byte addressable, and each integer takes up 4 bytes of memory, and say we allocate 40 bytes of memory to the pointer p from address 0 to 39.
Now, from what I understand, the pointer p initially contains value 0, i.e. the address of first memory location. In the loop, a displacement is added to the pointer to access the subsequent integers.
I cannot understand how the memory addresses uptil 39 are accessed with a displacement value of only 0 to 9. I checked and found that the pointer is incremented in multiples of 4. How does this happen? I'm guessing it's because of the integer type pointer, and each pointer is supposedly incremented by the size of it's datatype. Is this true?
But what if I actually want to point to memory location 2 using an integer pointer. So, I do this: p = 2. Then, when I try to de-reference this pointer, should I expect a segmentation fault?
Now, from what I understand, the pointer p initially contains value 0
No, the pointer p would not hold the value 0 in case malloc returns successfully.
At the point of declaring it, the pointer is uninitialized and most probably holds a garbage value. Once you assign it to the pointer returned by malloc, the pointer points to a region of dynamically allocated memory that the allocator sees as unoccupied.
I cannot understand how the memory addresses uptil 39 are accessed
with a displacement value of only 0 to 9
The actual displacement values are 0, 4, 8, 12 ... 36. Because the pointer p has a type, in that case int *, this indicates that the applied offset in pointer arithmetics is sizeof(int), in your case 4. In other words, the displacement multiplier is always based on the size of the type that your pointer points to.
But what if I actually want to point to memory location 2 using an
integer pointer. So, I do this: p = 2. Then, when I try to
de-reference this pointer, should I expect a segmentation fault?
The exact location 2 will most probably be unavailable in the address space of your process because that part would either be reserved by the operating system, or will be protected in another form. So in that sense, yes, you will get a segmentation fault.
The general problem, however, with accessing a data type at locations not evenly divisible by its size is breaking the alignment requirements. Many architectures would insist that ints are accessed on a 4-byte boundary, and in that case your code will trigger an unaligned memory access which is technically undefined behaviour.
Now, from what I understand, the pointer p initially contains value 0
No, it contains the address to the first integer in an array of 10. (Assuming that malloc was successful.)
In the loop, a displacement is added to the pointer to access the subsequent integers.
Umm no. I'm not sure what you mean but that is not what the code does.
I checked and found that the pointer is incremented in multiples of 4. How does this happen?
Pointer arithmetic, that is using + - ++ -- etc operators on a pointer, are smart enough to know the type. If you have an int pointer a write p++, then the address that is stored in p will get increased by sizeof(int) bytes.
But what if I actually want to point to memory location 2 using an integer pointer. So, I do this: p = 2.
No, don't do that, it doesn't make any sense. It sets the pointer to point at address 0x00000002 in memory.
Explanation of the code:
int *p; is a pointer to integer. By writing *p = something you change the contents of what p points to. By writing p = something you change the address of where p points.
p = (int *)malloc(sizeof(int[10])); was written by a confused programmer. It doesn't make any sense to cast the result of malloc in, you can find extensive information about that topic on this site.
Writing sizeof(int[10]) is the same as writing 10*sizeof(int).
*(p+i) = 0; is the very same as writing p[i] = 0;
I would fix the code as follows:
int *p = malloc(sizeof(int[10]));
if(p == NULL) { /* error handling */ }
for (int i=0; i<10; i++)
{
p[i] = 0;
}
free(p);
Since you have a typed pointer, when you perform common operations on it (addition or subtraction), it automatically adjusts the alignment for your type. Here, since on your computer sizeof (int) is 4, p + i will result in the address p + sizeof (int) * i, or p + 4*i in your case.
And you seem to misunderstand the statement *(p+i) = 0. This statement is equivalent to p[i] = 0. Obviously, your malloc() call won't return you 0, except if it fails to actually allocate the memory you asked.
Then, I assume that your last question means "If I shift my malloc-ated address by exactly two bytes, what will occur?".
The answer depends on what you do next and on the endianness of your system. For example:
/*
* Suppose our pointer p is well declared
* And points towards a zeroed 40 bytes area.
* (here, I assume sizeof (int) = 4)
*/
int *p1 = (int *)((char *)p + 2);
*p1 = 0x01020304;
printf("p[0] = %x, p[1] = %x.\n", p[0], p[1]);
Will output
p[0] = 102, p[1] = 3040000.
On a big endian system, and
p[0] = 3040000, p[1] = 102
On a little endian system.
EDIT : To answer to your comment, if you try to dereference a randomly assigned pointer, here is what can happen:
You are lucky : the address you type correspond to a memory area which has been allocated for your program. Thus, it is a valid virtual address. You won't get a segfault, but if you modify it, it might corrupt the behavior of your program (and it surely will ...)
You are luckier : the address is invalid, you get a nice segfault that prevents your program from totally screwing things up.
It is called pointer arithmetic. Add an integer n to a pointer of type t* moves the pointer by n * sizeof(t) elements. Therefore, if sizeof(int) is 4 bytes:
p + 1 (C) == p + 1 * sizeof(int) == p + 1 * 4 == p + 4
Then it is easier to index your array:
*(p+i) is the i-th integer in the array p.
I don't know if by "memory location 2" you mean your example memory address 2 or if you mean the 2nd value in your array. If you mean the 2nd value, that would be memory address 1. To get a pointer to this location you would do int *ptr = &p[1]; or equivalently int *ptr = p + 1;, then you can print this value with printf("%d\n", *ptr);. If you mean the memory address 2 (your example address), that would be the 3rd value in the array, then you'd want p[2] or p + 2. Note that memory addresses are usually in hex and wouldn't actually start at 0. It would be something like 0x092ef000, 0x092ef004, 0x092ef008, . . .. All of the other answers aren't understanding that you are using memory addresses 0 . . . 39 just as example addresses. I don't think you honestly are referring to the physical locations starting at address 0x00000000 and if you are then what everyone else is saying is right.

Resources