Pointers to arrays - c

I found an example of a pointer to array which to me doesn't make much sense, I was wondering if anybody would be able to help me?
int a[5] = 0,1,4,89,6;
int *p = a; 'p points at the start of a'
p[3] = 1; 'a[3] is now 6'
I'm not sure how the third line, p[3] = 1, works and how it causes a[3] = 6. Thanks for the help in advance.

It is bit incorrect. a[3] is 1, not 6.
Here are explanation line by line:
int a[5] = 0,1,4,89,6;
int *p = a; //'p points at the start of a'
p[3] = 1; //'a[3] is now 1 not 6'
First line initialize the array. I think there should be {} around numbers, but if compiles with you then is OK. This is how I believe it should be:
int a[5] = {0,1,4,89,6};
Second line create pointer to int p and initialize it to the address of a. Arrays and pointers are closely related in C, so now, you have 2 variables a and p pointing to one and same memory address.
Third line - you set p[3] to 1, this time you access p as array of int (it is possible because of that relationship between arrays and pointers). Because p and a points in same memory address, this means a[3] is now 1
Also remarks are incorrect, must be /* */ or //.
UPDATE :
David's comment is very important.
Arrays are sequential reserved memory capable to store several array values, in your case 5 int's.
A pointer is a pointer and may point everywhere they can point to int variable:
int a = 5;
int *b = &a;
or they can point to array as in your case. In both cases you will be able to use [], but in case it points to single value, any array subscript greater than zero will be wrong, e.g.
int a = 5;
int *b = &a;
*b = 4; // OK.
b[0] = 4; // OK.
b[1] = 4; // compiles correctly, but is **wrong**.
// it will overwrite something in memory
// and if program not crash,
// it will be security hole.
int x[10];
int *y = x;
*y = 4; // works correctly for y[0],
// but makes it difficult to read.
y[0] = 5; // OK
y[9] = 5; // OK
y[10] = 5; // compiles correctly, but is **wrong**.
// it is after last element of x.
// this is called **buffer overflow**.
// it will overwrite something in memory
// and if program not crash,
// it will be security hole.
UPDATE :
I recommend you check this article
http://boredzo.org/pointers/

Related

Pointer Subtraction in C with an array

If I have the following lines of code, why is b-a = 2?
int a[] = {1,2,3,4,5};
int *b = &(a[2]);
To elaborate slightly on Eugene's answer, a is a pointer to the beginning of the array, and a[2] is the same as *(a+2).
So you could say that the & "cancels" the * as you dereference the pointer and then look at the address of the element that it points to. So *b = &(a[2]) = &(*(a+2)) = a+2.
Therefore b-a=2

Structures and linked list accessing.

#include <stdio.h>
int main(void)
{
typedef struct{
int a;
} cool;
cool x;
(&x)->a = 3;
x.a = 4;
}
I was wondering if the (&x)-> a does the same thing as the x.a. I coded both of them up, and it seemed that both of them changed the value of x.a. I know it must be a pointer on the left side of ->, but the (&x) seems to work without problem. Printing out x.a works for both of them, and gives me the correct answer. I looked up a lot about pointers, linked list, and structures and am still not able to find out the answer. Would it be possible to get an explanation? Thank you!
The -> operator expects a pointer on the left hand side. &x returns the address of x so it satisfies that requirement (even if it is totally redundant). To think about it another way...
cool *y = x;
y->a = 3;
The . operator expects a stack allocated struct on the left hand side. x is that, so x.a works fine.
You can also go the other way, if you have a pointer y you can dereference it with *y and use . on it: (*y).a. This is also totally redundant.
The & prefix operator returns the memory address of whatever object you put it in front of.
This means that you have to put it in front of objects that actually have a memory address. For example, literals and temporary expression results don't necessarily have an address. Variables declared with register storage class don't have an address, either.
Thus:
int i = 5;
&i; // works
&5; // Nope!
&(i + 1); // Nope!
&i + 1; // Works, because &i has higher precedence than +1.
So what does the address of an object give you? It is a pointer to the object. This is how you can do dynamic memory allocation using the heap. This is where functions like malloc() come in. And this is how you can build arbitrarily large data structures.
In C, arrays are represented as pointers. So arrays and pointers are often used interchangeably. For example:
char buffer[100]; // array
strcpy(buffer, "hello"); // strcpy is declared to take (char *, const char *)
The opposite of the address_of operator is the * dereference operator. If I declare a pointer to something, I can get "what it points at" using this syntax:
int i = 5;
int *pi = &i; // pointer to int. Note the * in the declaration?
i + i; // 10
i + *pi; // Also 10, because pi "points to" i
In the case where you have an aggregate type like a struct or union, you would have to do something like this:
struct {
int a;
} s;
s.a = 5;
/* ??? */ ps = &s; // pointer to s
s.a; // 5
(*ps).a; // Also 5, because ps points to s.
ps->a; // 5, because a->b is shorthand for (*a).b
This only works, of course, if you have a pointer to an object that CAN use the .member and that has an appropriately named member. For example, you can't do this:
i = 5;
pi = &i;
pi->a; // WTF? There is no i.a so this cannot work.
If you have a pointer, you can take the address of it. You then have a pointer to a pointer. Sometimes this is an array of pointers, as with the argv array passed to main:
int main(int argc, const char *argv[]);
int main(int argc, const char **argv); // Effectively the same.
You can do weird stuff with pointers to pointers:
int i = 5;
int j = 100;
int * pij;
for (pij = &i; i < j; ) {
if (i & 1) {
*pij *= 2;
pij = &j;
}
else {
i += 1;
*pij -= 1;
pij = &i;
}
}
Note: I have no idea what that code does. But it's the kind of thing you can wind up doing if you're working with pointers.

Strange output with pointer arithmetic

Can anyone explain the reason behind the second output? Also what is the difference between solving using int pointers and char pointers?
The second answer is coming out to be 0.
int main()
{
char arr[] = "geeksforgeeks";
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;
}
Pointers of some type T point to objects of type T.
For example
int a[] = { 1, 2 };
int *p = a;
If you increase a pointer as for example
++p;
or
p = p + 1;
(take into account that these statements are equivalent) it will point to the next object of type T that follows the current object. So the value of the pointer will be increased by sizeof( T ) that to provide that the poiner indeed will point to the next element.
In the example above sizeof( int ) is (usually) equal to 4. So the value of the pointer will be increased by 4.
If you write
int a[] = { 1, 2 };
int *p = &a[0]; // the same as int *p = a;
int *q = &a[1];
then expression q - p will be equal 1 but the difference between the values stored in p and q will ve equal to sizeof( int ). p points to the first element of the array and q points to the second element of the array. It is so-called pointer arithmetic.
As for your result with subtracting int pointers then the behaviour is undefined. According to the C++ Standard
Unless both pointers point to elements of the same array object, or one
past the last element of the array object, the behavior is undefined
In your case int pointers do not point to elements of the same array. That they would point to the elements of the same array at least the difference of their values shall be equal to sizeof( int )
It's happen because char size is 1-byte, when int is 32Bit (4byte) variable
Edit keep pointer in the original array and ensure correct alignement to avoid undefined behaviour (see comment of Matt McNabb)
Because 3 < sizeof(int).
In pointer arithmetic, (int *) ptr2 - (int *) ptr1 gives real_addr_of_ptr2 - real_addr_of_ptr1) / sizeof(int) = 3 / 4. As it is integer division => 0 - this is not specified by C++ but is current implementation.
If you use : char *ptr2 = ptr1 + 8;, you will get : (int*)ptr2 - (int*) ptr1 = 2
As there are more than 8 characters in array, it can work, provided the original array is correctly aligned. To be coherent with the specs, it should have been declared :
union {
char arr[] = "geeksforgeeks";
int iarr[];
} uarr;
char *ptr1 = uarr.arr;

Why do these pointers cause a crash?

I'm a bit confused as to why the following code crashes:
int main(){
int *a;
int *b;
*a = -2;
*b = 5; //This line causes a crash on my system.
return 0;
}
Shouldn't memory automatically be allocated for two pointers and two integers before run-time because of the declarations?
Or must you always explicitly allocate memory?
No. You've only declared the pointers, not what they point to. The pointers are allocated on the stack, and since you've not initialized them to anything, their values are garbage.
int main() {
int a = 7;
int *p_a; // p_a contains whatever garbage was on the stack at its
// location when main() is called. (Effectively points nowhere).
p_a = &a; // p_a points to (gets the address of) variable a, also on
// the stack.
printf("Before: a = %d\n", a); // prints 7
*p_a = -2;
printf("After: a = %d\n", a); // prints -2
return 0;
}
I would code up the above example, and step through it in a debugger. You'll see what I mean about what p_a is pointing to.
Shouldn't memory automatically be allocated for two pointers and two integers before run-time because of the declarations?
I only see you specifying two pointers. Where are the two integers?
Or must you always explicitly allocate memory?
Pointers have to point to something. Either local variables on the stack, or malloc'd memory from the heap.
In this code:
int* a;
*a = -2;
a is an uninitialized pointer, dereferencing of which produces undefined behavior, that you were luckily able to observe as a crash of your application.
You need to initialize the pointer (make it point to the valid memory) before you dereference it (i.e. before you use *, the dereference operator):
int a;
int* pA = &a;
*pA = -2;
Consider
int m;
int n;
m = n;
This is invalid because you're trying to use n but you haven't assigned a value to it. Now:
int *a;
*a = -2;
Likewise, this is invalid because you're trying to use a but you haven't assigned a value to it. The value of a is not an int, it's a pointer to int. For example,
int someint;
a = &someint;
*a = -2;
puts -2 into someint. Without the assignment to a, the place to put -2 is undeterminable. Also,
a = malloc(sizeof(int));
*a = -2;
Here, a is given the value of the address of some location in the heap; -2 goes into that heap location.
Perhaps an analogy would be helpful:
Consider the phrase "her dog". This is a reference to someone's' dog, but it won't do to tell me "give her dog a bone" if you haven't told me who she is. Similarly, "pointer to an int" doesn't tell the system which int it is.
Your *a and *b pointers are not initializated properly.
Try this one:
int my_a;
int my_b;
int *a;
int *b;
a = &my_a; // init the pointer a to the direction of my_a int variable
b = &my_b;
*a = 3; // set the my_a value via pointer
*b = 2;
You have just declared pointers but you haven't initialized them. So, you can't be sure that *b = 5 is causing the program to crash. It could be *a = -2 as well. To fix it, you should initialize your pointers as well.
int aval = -2;
int bval = 5;
int *a = &aval; // declared and initialized pointers
int *b = &bval;
// Now you can change the value using the pointer
*a = 15;
*b = 20;

Array Assignments in C Using Pointer Arithmetic

How can I change the value in an array when I access a particular element using pointer arithmetic?
#include <stdio.h>
int main() {
int a[3] = {1, 1, 1}, b[3] = {2, 2, 2};
a++ = b++; // How can I get this to work so a[1] = b[1]?
return 0;
}
Arrays are not pointers. Repeat this three times; arrays are not pointers.
You cannot increment an array, it is not an assignable value (i.e., you cannot mutate it). You can of course index into it to get a value back:
a[1] = b[1];
Secondly, your current code is attempting to increment and then assign a new value to the array itself, when you meant to assign to an element of the array. Arrays degrade to pointers when required, so this works too:
int *a_ptr = a;
int *b_ptr = b;
*++a_ptr = *++b_ptr;
// or, better...
a_ptr[1] = b_ptr[1];
Which is what you meant to do. I prefer version 1 and, more often than not, use indexing with pointers as well because it is often easier to read.
How can I get this to work so a[1] = b[1]?
Simple:
a[1]++;
if you just wanted to increment a[1] (1) to be what b[1] happens to be (2), or
a[1] = b[1];
if you want a[1] to have the same value as b[1] regardless of what that value is.
when I access a particular element using pointer arithmetic?
In your example, you are not accessing any element, nor are you doing pointer arithmetic because a and b are arrays, not pointers. The formulation of your question is difficult to interpret, both because of that and because
a++ = b++;
1) is completely meaningless 2) would not be legal C even if a and b were pointers, because the left side must be an lvalue, but a++ is not 3) is not discernably related to your wish for a[1] to be the same as b[1]. Possibly what you want is:
int* ap = a; // get pointer to first element of a
int* bp = b; // get pointer to first element of b
// point ap to second element of a and
// point bp to second element of b and
// copy the value at *bp to *ap
*++ap = *++bp;
That would indeed set a[1] to b[1].
Your arrays in this case are not actually pointers. They are converted by the compiler when they are accessed as pointers, but I don't believe that you're allowed to do something like a++.
If you want to do this with arithmetic, you'll need actual pointers:
int *ap = a, *bp = b;
*ap++ = *bp++;
That is like doing a[0] = b[0]; and then moving each pointer to the next element in their associated array.
But your question says you want to set a[1] = b[1]. Well, you could do this:
*++ap = *++bp;
Or you could just use the array indices and make it much more obvious what you're doing.

Resources