I have just started diving into pointers in C and I can't understand why 14 is the output.
I have the given code:
#include<stdio.h>
#include<stdlib.h>
#define N 3
typedef int(*MyType1)[N];
typedef int(*MyType2)[N][N];
int main(int argc, int *argv[]){
int m1[][N] = { 21,122,-13,14,56,36,17,78,92 };
int m2[][N] = { 11,9,43,17,32,99,127,34,69 };
MyType1 p1[] = { m1 + 1,m2 + 2,m1+2,m2,m1,m2+1};
MyType2 p2[] = { &m2, &m1 };
printf("%d\n", **(p2[1][0] + 1));
return 0;
}
My thought was:
**(p2[1][0] + 1) is equivalent to **(&m1[0] + 1).
Then, &m1[0] is the address of the first element in m1 (21), plus one increments the address to the number next to it (122).
I noticed that every plus one accessed the n + 3 number in m1 (goes down a row in m1?) --> The question is why.
Well...
p[1] is a pointer to m1.
m1 might also have been initialized: {{21,122,-13},{14,56,36},{17,78,92}}.
So p[1][0] is a pointer to the first array: {21, 122, -13} but then we do some pointer arithmetic and point to the next array: {14,56,36} and when we dereference that we get the first element which is... 14.
Related
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.
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.
Hi Friends,
I am new to C. I am trying to learn it, I got stuck some where in arrays. Please check following program
#include <stdio.h>
#include <stdlib.h>
int arr1[] = {10,20,30,40,50};
int arr2[] = {5,15,25,35,45};
int *main_arr[] = {arr1,arr2};
int main()
{
printf("in first array 0th locatin value is: %d\n",*main_arr[0]);
system("PAUSE");
return 0;
}
By using printf i can print the value at 0th location, but not getting how to access rest of the element ...please help me!
You want
...: %d\n",(main_arr[0])[0]);
------------- ->arr1
--- ->arr1[0]
main_arr is pointing to both arrays arr1, arr2. So main_arr[0] points to the first element of the first array. To access other elements modify the 2nd [0].
Check it out
The other alternative, uglier but closer to your current code, is to use pointer arithmetic.
...s: %d\n",*(main_arr[0]+1));
Remember that arr[1] is the same as *(arr+1).
#include <stdio.h>
#include <stdlib.h>
int arr1[] = {10,20,30,40,50};
int arr2[] = {5,15,25,35,45};
int *main_arr[] = {arr1,arr2};
int main()
{
int iter1, iter2;
for(iter1 = 0; iter1 < 2; iter1++){
for(iter2 = 0; iter2 < 5; iter2++){
printf("in first array nth locatin value is: %d\n",(main_arr[iter1][iter2]));
}
}
system("PAUSE");
return 0;
}
I guess the code is simple enough to be understood?
There are only two pointers in the main_arr, pointing to address of arr1 and arr2.
main_arr| ptr to an array | -> arr1
| ptr to an array | -> arr2
So you can use main_arr[0][1] to access the second element of arr1, because main_arr[0] points to the address of the very first element of arr1.
You should have know that in C, if p is a pointer, then both p[3] and 3[p] will evaluate to *(p + 3 * sizeof(type)), so let's assume p = main_arr[0], then p[1], which is main_arr[0][1], will evaluate to *(main_arr[0] + 1 * sizeof(int)), which is the same value with arr1[1].
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
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.