Pointer arithmetic and address - c

I have come across a code which goes like :
#include <stdio.h>
int main(void)
{
int a[5] = { 1, 2, 3, 4, 5};
int *ptr = (int*)(&a + 1);
int *ptr2 = (int*) &a;
ptr2 +=1 ;
printf("%d %d %d \n", *(a + 1),*(ptr - 1) ,*ptr2 );
return 0;
}
The pointer arithmetic does it for me except this line :
int *ptr = (int*)(&a + 1);
Is it undefined behaviour ?
Why do we get 5 on dereferencing *(ptr - 1) ?

The size of a is "5 ints". So &a + 1 refers to the first memory location past all of a, since the pointer arithmetic is done in units of the size of a.

Try it out!
int a[5] = {1, 2, 3, 4, 5};
printf("%#x, %#x, %#x, %#x\n", a, &a, a+1, &a+1);
0xbfa4038c, 0xbfa4038c, 0xbfa40390, 0xbfa403a0
So what does that tell us?
0xbfa4038c == 0xbfa4038c which means a == &a. This is the address of the first element in the array or a[0].
We know that the size of an int is 4, and you know that *(a+1) == a[1] (the second element in the array) and this is proven by:
0xbfa4038c + 0x4 = 0xbfa40390 which means a + one int = address of the next element
Thus if we see &a+1 == 0xbfa403a0, that means we're ((0xa0-0x8c)/4) = 5 elements into the array. You know that a[5] is invalid, so that means we're one passed the end of the array.
so if you take:
int *ptr = (int*)(&a + 1); //one passed last element in the array
printf("%d",*(ptr - 1));//back up one, or last element in the array and deference
That's why you get 5

For an array of n elements of type T, then the address of the first element has type ‘pointer to T’; the address of the whole array has type ‘pointer to array of n elements of type T’;
int *ptr = (int*)(&a + 1); //&a-> address whole array, size=20 bytes,
//ptr=&a+1: next element =adress of a +20 bytes.
//ptr - 1 = address of a +16 = address of last a's element = address of 5

Related

Trying to load an array using pointers in C

I am trying to load an array using pointers. I am assigned my x[0] the value of 2, and the desired output is 2, 4, 8, 16, 32, 64, 128.
For some reason, my loop starts at index 4 or it starts at index 2 and only prints 2, 4, 8, 16.
#include <stdio.h>
#include <math.h>
int main() {
int x[7] = {}, *ip;
ip = &(x[0]);
*ip = 2;
for(int i = 0; *ip < sizeof x; *ip *= 2) {
printf("value of x: %d\n", x[i]);
}
}
This loop:
for(int i = 0; *ip < sizeof x; *ip *= 2) {
printf("value of x: %d\n", x[i]);
}
will print x[i] till the value at memory location pointed by pointer ip is less than the size of object x in bytes. Note that i is initialised with 0 but it is nowhere altered.
Assume that size of int on your system is 4 bytes, the sizeof x will yield 28 because x is an array of 7 integers (7 * 4 = 28).
Iteration I:
i = 0 //initialized
*ip = 2, 2 < 28 ----> true
print x[0] ----> 2
*ip *= 2 ----> *ip = 4
Iteration II:
*ip = 4, 4 < 28 ----> true
print x[0] ----> 4
*ip *= 2 ----> *ip = 8
Iteration III:
*ip = 8, 8 < 28 ----> true
print x[0] ----> 8
*ip *= 2 ----> *ip = 16
Iteration IV:
*ip = 16, 16 < 28 ----> true
print x[0] ----> 16
*ip *= 2 ----> *ip = 32
Iteration V:
*ip = 32, 32 < 28 ----> false
loop exits
Hence, you are getting output - 2, 4, 8, 16.
Correct way to get the size of an array is - sizeof (x) / sizeof (x[0]). This will result in number of elements of array x.
This
ip = &(x[0]);
can also written as
ip = x;
because when you access an array, it is converted to a pointer to first element (there are few exceptions to this rule). Moreover,
From C Standards#6.5.2.1
The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2)))..
by this definition
&(x[0]) -> &(*(x + 0)) -> &(*(x)) -> x
You are initialising the array x with an empty initialiser:
int x[7] = {}
Empty initialiser is non-conforming in C, though some C compilers accept it. Instead, you should do:
int x[7] = {0}
Your desired output is 2, 4, 8, 16, 32, 64, 128 i.e. the first element of array should be 2 and every successive element in the array should be multiple of 2 of its previous element. Since, you want to calculate the value of every element of array using pointer pointing to that array element, one things you should know -
A pointer can point to one past the last element of array but dereferencing it will invoke undefined behaviour.
Putting these altogether, you can do:
#include <stdio.h>
int main (void) {
int x[7] = {0}, *ip;
ip = x;
*ip = 2;
for (size_t i = 0; i < sizeof (x) / sizeof (x[0]); ++i) {
printf ("value of x: %d\n", x[i]);
// make pointer point to next element in array
++ip;
// make sure that the element that ip pointer pointing to is valid to deference
if (ip < x + (sizeof (x)/sizeof (x[0]))) {
// calculate the element value using the previous element value
*ip = *(ip - 1) * 2;
}
}
return 0;
}
If you want to avoid the pointer comparison, you may do something like this:
#include <stdio.h>
int main (void) {
int x[7] = {0}, *ip;
ip = x;
for(size_t i = 0; i < sizeof (x) / sizeof (x[0]); ++i, ++ip) {
*ip = (i ? *(ip - 1) : 1) * 2;
printf("value of x: %d\n", x[i]);
}
return 0;
}
Following the perceived intent of your code, that is, to fill an array by using a pointer, I corrected it to the below.
#include <stdio.h>
int main()
{
int x[7] = {0};
int *p, counter;
for (p = &x[0], counter = 0; counter < 7;) {
*p++ = (1 << ++counter);
}
for (counter = 0; counter < 7; counter++)
printf("%d\n", x[counter]);
}
I initialise x and declare a pointer int *p. I also declare a variable counter to count to the number of elements in the array.
At the start of the loop I point p to the address of the first element of the array x and initialise counter to 0.
In each loop iteration I set the value at the address pointed by p to the result of a left-shift (or l-shift) operation and increment pointer p (that is, advance it by sizeof(int) bytes). The l-shift operation has the effect of raising 2 to the power of n, where n is the number of l-shift positions. For example:
(1 << 0) = 1
(1 << 1) = 2
(1 << 2) = 4
(1 << 3) = 8
I use the post-increment operator for p (that is, *p++) because I want to set the value before advancing it. But I use the pre-increment operator for counter (that is, ++counter) because I want the first l-shift to be by 1 position so that the result stored in the first element of the array is 2 -- refer to example above.
int x[7] = {}, *ip;
ip = &(x[0]);
In C, arrays are just pointers that you've told the proprocessor and compiler about so it can do the memory allocation on the stack for you. There's nothing special about the pointer itself with an array. In the above, ip and x are both int*, so you can just say ip = x;
*ip = 2;
x[0] now is 2
for(int i = 0; *ip < sizeof x; *ip *= 2){
Your middle condition *ip < sizeof x; in English is "until the int pointed to by ip is less than the number of bytes used by x (7 * sizeof(int); probably 7 * 4 or 28)" It's valid in that it will compile and execute, but I don't think it's what you want looking at the rest of your code. You never increment ip, so it's always changing x[0].
Assuming you just don't want ip to go past the end of x[], You could write this as i < sizeof(x)/sizeof(x[0]) which is "counter i is less than the total bytes used by x[] divided by the size in bytes of one element used by x (the number of elements in x[])" or if you want to use ip and not i for some reason ip <= &x[6] which is "ip is less than or equal to the address of the last element of x[] (because we know x is a fixed length of 7; [0...6]"
*ip *= 2
Your for incrementor is "the integer pointed to by ip is multiplied by 2". Normally you would increment your counter i here, but it's acceptable in C to do something else like you have here. However, since you never change ip, this is going to multiply the same x[0] by 2 over and over until x[0]'s value is more than sizeof(x). You probably want to increment ip or i here, so it steps through X[]. Normally the manipulation of your array would happen inside the for block and not in the for control statements.
printf("value of x: %d\n", x[i]);
This will always print the value of x[0], since i never changes.
Everything you've written is valid C code. Some of the things you're doing are unusual, but there are edge cases where you would want that in C, for example incrementing something other than your counter in the for loop control. However, you've got a extra code that isn't doing anything useful. I see what you want as output from your question details, but from your code I'm unsure how you want to accomplish that, so this is just a guess:
int x[7];
x[0] = 2;
printf("x[0] starts with: %d\n",x[0]);
for(int i = 1; i<sizeof(x)/sizeof(x[0]); i++) { //i start at 1 because we already set x[0]
x[i] = x[i-1]*2; //the current x[] = double the previous x[]
printf("value of x[%d]: %d\n",i,x[i]);
}
This version fills x with [2,4,8,16,32,64,128]. The int *ip isn't needed- there are times you'll want to control a loop with pointer math, but it's not needed here.

Why A[2][3] is valid lvalue for the declaration int *A [10];

int *A [10];
why A[2][3] is a valid lvalue. As I understand in A[2] we store a pointer to an integer(Single integer not an array). So how can [3] in A[2][3] access it?
Hopefully this code can demonstrate how int pointer arrays can be used.
The goal is to create a buffer big enough to hold 30 integers. Then assign an int pointer to every 3rd address division of the allocated buffer.
So if a[0] is set to address 0x562437eea260.
Then that means a[1] will be set to address 0x562437eea26c approximately (sizeof(int) * 3), 12, bytes away.
Then the values at the pointer's address can be set by calling a[i][j]; assuming i is the index that chooses the address from the int pointer array and j is either 1, 2, or 3 depending on what number you wish to access.
Expected Output:
a[0] = 0x562437eea260
a[0][0] = 2
a[0][1] = 3
a[0][2] = 5
a[1] = 0x562437eea26c
a[1][0] = 3
a[1][1] = 3
a[1][2] = 7
a[2] = 0x562437eea278
a[2][0] = 9
a[2][1] = 2
a[2][2] = 3
In my example, I set all integers to random values
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define UNUSED(x)((void)(x))
#define TOTAL_INT_POINTERS 10
#define INTS_PER_POINTER 3
int main(const int argc, const char** const argv, const char** const envp) {
UNUSED(argc); UNUSED(argv); UNUSED(envp);
// Seed random number generator
srand((unsigned int)time(0));
// Create and array that will hold 10 int pointers
int *a[TOTAL_INT_POINTERS] = {0};
// Allocate memory for integers
int *ptr = (int *)malloc((sizeof(int) * TOTAL_INT_POINTERS) * INTS_PER_POINTER);
if(ptr == NULL) {
fprintf(stderr, "Failed to allocate memory for integers!\n");
return (int)EXIT_FAILURE;
}
// Assign pointers and values to each allocated space
for(unsigned int i = 0; i < TOTAL_INT_POINTERS; i++) {
// Assign pointer array member
a[i] = ptr + (i * INTS_PER_POINTER);
// Print assigned address
printf("a[%d] = %p\n", i, a[i]);
// Give 3 integers their values and print out the result
for(unsigned int j = 0; j < INTS_PER_POINTER; j++) {
a[i][j] = rand() % 10;
printf("a[%d][%d] = %d\n", i, j, a[i][j]);
}
putchar('\n');
}
// Free up used memory
free(ptr);
return (int)EXIT_SUCCESS;
}
As already pointed out in the comments, the compiler manages only the pointer and is not aware of the actual structure of your data. You can access array elements by index using square brackets or by using pointer arithmetics:
A[i][j] is equivalent to *(A[i] + j) and also equivalent to *(*(A+i) + j).
Note that you must ensure that the memory you are accessing is actually within the array bounds.
Further reading:
Multidimensional Pointer Arithmetic in C/C++
How to access two dimensional array using pointers in C programming?
The fact that x points to an int does not mean there are not more int next to that int, either before or after it or both.
If I have an array int a[10], then &a[5] points to element 5 of the array, and &[5] - 1 and &a[5] + 1 point to elements 4 and 6. If I pass &a[5] to a subroutine as its parameter int *x, and that subroutine knows other elements exist, it may use x[1] to refer to element 6 of the array and x[-1] to refer to element 4.
Given int *A[10], I can allocate as much memory as I want and assign its address to A[0]. Then A[0][0] points to space for the first int in that memory, A[0][1] points to space for the next int, and so on.

I am confused how to understand this code. contains double pointers

I don't understand why the code below changes the array b:
int a[] = { 3, 6, 9 };
int b[] = { 2, 4, 6, 8, 10 };
int **c;
int **d[2];
c = (int **)malloc (b[1] * sizeof(int *));
*c = &a[1];
c[1] = c[0] + 1;
*d = c;
c = c + 2;
*c = b;
c[1] = &c[0][3];
*(d + 1) = c;
d[0][3][1] = d[1][0][0];
d[1][0][2] = d[0][1][0];
I have run this code and found the values of array a and array b but I am unable to understand how these values come.
Array a remains unchanged while b becomes 2, 4, 9, 8, 2. How does this happen?
c = (int**)malloc(b[1] * sizeof(int*)); //int **c[4] ???
c is an array of double pointers *c = &a[1] this means that c[0] has the address of array a's second index. I am not getting the way to interpret this.
The code contains actual statements, therefore it must be part of a function body, hence all declarations herein have automatic storage. It is highly convoluted, with purposely contrived double indirections... Lets analyse it one line at a time:
int a[] = { 3, 6, 9 }; -- a is an array of 3 ints initialized with some explicit values.
int b[] = { 2, 4, 6, 8, 10 }; -- likewise, b is an array of 3 ints initialized with some explicit values.
int **c; -- c is an uninitialized pointer to a pointer to int, that can be made to point to an array of pointers to int.
int **d[2]; -- d is an uninitialized array of 2 pointers to pointers to int, each of which can be made to point to an array of pointers to int.
c = (int **)malloc(b[1] * sizeof(int *)); -- c is set to point to a block of uninitialized memory with a size of 4 pointers to int. In short, c now points to an uninitialized array of 4 pointers to int.
*c = &a[1]; -- The element pointed to by c (aka A[0]) is set to point to the second element of a (aka a[1], with a value of 6). The value of A[0] is &a[1].
c[1] = c[0] + 1; -- The second element in the array pointed to by c (aka A[1]) is set to point to the element after the one pointed to by c[0], hence it points to the third element of a (aka a[2] with a value of 9). The value of A[1] is&a[2]`.
*d = c; -- The first element of d is set to the value of pointer c, which is the address of A[0]. The value of d[0] is &A[0].
c = c + 2; -- The pointer c is incremented by 2, it now points to the third element of the array A allocated with malloc(), A[2].
*c = b; -- The element pointed to by c, A[2], which is itself a pointer, is set to point to the first element of b, b[0]. The value of A[2] is &b[0].
c[1] = &c[0][3]; -- The element after that, A[3], the 4th element of the array allocated by malloc, is set to point to the 4th element of the array pointed to by the element c points to. &c[0][3] is equivalent to c[0] + 3 or &(*c)[3] or simply *c + 3. This element is b[3] which has the value 8. The value of A[3] is&b[3]`.
*(d + 1) = c; -- This is equivalent to d[1] = c; which sets the second element of d to the value of the pointer c, which is the address of the 3rd element of the array allocated wth malloc(), A[2], which points to b[0]. The value of d[1] is &A[2].
d[0][3][1] = d[1][0][0]; -- Let's rewrite these terms:
d[0][3][1] => (&A[0])[3][1] => A[3][1] => (&b[3])[1] => *((b + 3) + 1) => b[4]
d[1][0][0] => (&A[2])[0][0] => (*&A[2])[0] => A[2][0] => (&b[0])[0] => b[0] which is the value 2.
Hence b[4] = 2;.
d[1][0][2] = d[0][1][0]; -- Let's rewrite these:
d[1][0][2] => (&A[2])[0][2] => (*&A[2])[2] => A[2][2] => (&b[0])[2] => (b + 0)[2] => b[2].
d[0][1][0] => (&A[0])[1][0], ie A[1][0] => (&a[2])[0] => *&a[2] => a[2] that has a value of 9.
Hence b[2] = 9;
As a consequence, the array b now has elements { 2, 4, 9, 8, 2 }.
You can run the program:
#include <stdio.h>
#include <stdlib.h>
int main() {
int a[] = { 3, 6, 9 };
int b[] = { 2, 4, 6, 8, 10 };
int **c;
int **d[2];
c = (int **)malloc (b[1] * sizeof(int *));
*c = &a[1];
c[1] = c[0] + 1;
*d = c;
c = c + 2;
*c = b;
c[1] = &c[0][3];
*(d + 1) = c;
d[0][3][1] = d[1][0][0];
d[1][0][2] = d[0][1][0];
printf("a = { ");
for (size_t i = 0; i < sizeof a / sizeof *a; i++)
printf("%d, ", a[i]);
printf("};\n");
printf("b = { ");
for (size_t i = 0; i < sizeof b / sizeof *b; i++)
printf("%d, ", b[i]);
printf("};\n");
return 0;
}

Pointers manipulation in c

I have a doubt in pointers manipulation...
main()
{ int x=10; // extra line added...
char *p=x;
printf("%d", &p)
printf("%d", &p[0]);
printf("%d" , &p[1]);
}
This code gives output
Address of 10..
10
11
how are the last two outputs are coming.. Can anyone explain it to me ..?
Code changed.....
This is Undefined Behavior.
The pointer needs to point to something valid before some value can be added to that location.
char a = 10;
char *p = &a;
Will explain two scenarios:
Scenario 1: char * p = x;
x == 10, p is a char pointer which is initialized with 10 (an address which user program can't access): p == 10
The value of p (ie, *p) will lead to segmentation fault (being invalid memory reference)
p[0] == *(p + 0) and &p[0] == (p+0) == p which is 10.
Hence printf("%p", &p[0]) will give you 10.
p[1] == *(p + 1) and &p[1] == (p+1)
Since, p is a character pointer, it gets increments by sizeof(char), ie 1
Hence printf("%p", &p[1]) will give you 10+1 = 11
Scenario 2: char * p = &x;
Here p is a char pointer pointing to integer x
Value of x = 10
Address of x = 1000 (assume)
Hence p = 1000
p[0] == *(p + 0) and &p[0] == (p+0) == p
Hence printf("%p", &p[0]) will give you 1000
p[1] == *(p + 1) and &p[1] == (p+1)
Since, p is a character pointer, it gets increments by sizeof(char), ie 1
ie &p[1] == 1000+1 == 1001
p and &p[0] will be evaluated to same address (address of first element of array) which is 10.
So &p[0] will be evaluated to 10 and &p[1] to &p[0] + sizeof(char) which is 11
Your code will most likely segfault though when you dereference p (*p).
Following code will always print True.
main()
{
int* p;
printf("%s\n",p == &p[0] ? "True" : "False");
}
Some errors in your code:
int x = 10;
char * p = &x; // error 1 - you was assigning int to pointer
printf("%p\n", &p); // error 2 - you printing address of pointer (char **),
// so different format string is needed
printf("%p\n", &p[0]); // same error 2 - printing address of first byte in int x
printf("%p\n" , &p[1]); // same error 2 - printing address of second byte in int x
printf("%d", &p[0]);
printf("%d" , &p[1]);
it will print out the address that p is pointered on..
because char *p=x; while x = 10;
then ,, &p[0] = 10, &p[1] = 11 &p[2] = 12 , and so on..
printf("%d", &p);
I'm not so sure about this, but as i know it will print out the value contained in memory 10 in my case = 10000
printf("%d", p);
it will print out the 10, which is the *p value;
cmiiw
char *p=10;
The code at present has undefined behavior. Pointer p is not pointing to any valid memory location to initialize 10 in that location.
With that said, both p, &p[0] yields the same memory location.

Character array and pointer

The code snippet is given as:
char *s[] = {"program", "test", "load", "frame", "stack", NULL};
char **p = s + 2;
We need to find the output of following statement:
printf("%s", p[-2] + 3);
What does p[-2] refer to?
char *s[] = {"program","test","load","frame","stack",NULL};
char **p = s + 2
printf("%s", p[-2] + 3);
The variable s is an array of char* pointers.
The variable p is a pointer to a pointer. Pointer arithmetics downgrades the array s to a char**, initializing p to a value of two times the size of a char**. On a 32bit machine, if s points to 1000, p will point to 1008.
The expression p[-2] is equivalent to *(p - 2), returning a simple pointer to a char*. In this case, a value pointing to the first element of the strings array: "program".
Finally, since *(p - 2) is the expression pointing to the first letter of the string "program", *(p - 2) + 3 points to the fourth letter of that word: "gram".
printf("%s", *(p - 2) + 3); /* prints: gram */
Did you try compiling your code? Once the syntax errors are fixed, the output is gram.
#include <stdio.h>
int main()
{
char *s[] = {"program","test","load","frame","stack",NULL};
char **p = s + 2;
printf("%s",p[-2] + 3);
return 0;
};
See http://ideone.com/eVAUv for the compilation and output.

Resources