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].
Related
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.
1)
How to access array element with array of pointers?
By pointer to an array we can access like this (∗a)[0]
,(∗a)[22]
,….. like this
right?
but how with array of pointer?
2)
Check these three codes , one of them use array and one of them use array of pointer, and 3rd one using double pointer, but all giving same output. Why??
#include <stdio.h>
int ptr[12];
int main(void) {
if(*(ptr+5)==*(ptr+3)){
printf("Equal");
}
else{
printf("Not Equal");
}
return 0;
}
#include <stdio.h>
int *ptr[12];
int main(void) {
if(*(ptr+5)==*(ptr+3)){
printf("Equal");
}
else{
printf("Not Equal");
}
return 0;
}
#include <stdio.h>
int **ptr[12];
int main(void) {
if(*(ptr+5)==*(ptr+3)){
printf("Equal");
}
else{
printf("Not Equal");
}
return 0;
}
In *(ptr+5):
ptr is the name of an array.
When an array is used in an expression and is not the operand of sizeof or unary & and is not a string literal used to initialize an array, it is converted to a pointer to its first element. So ptr points to element 0 of the array.
ptr+5 adds five, resulting in a pointer to element 5 of the array.
* dereferences the pointer, producing the contents of element 5 of the array.
Since the array is defined outside any function, it is initialized to zero. Therefore element 5 is zero, so *(ptr+5) is zero. Similarly, *(ptr+3) is zero, so comparing them shows they are equal.
The examples with int ptr[12];, int *ptr[12];, and int **ptr[12]; just change the types of the elements in the array. In each case *(ptr+5) and *(ptr+3) refer to elements 5 and 3 of the array. In each case, the values of the elements are zero (null pointers for the pointer types).
If you want to see differences between different elements of the array, then assign different values to the elements of the array.
Just keep incrementing the pointer as you go along reading the array. Analyze the
code below:
#include <stdio.h>
int main(void) {
int *ptr[3];
int a[] = { 0,1,2};
int b[] = { 3,4,5 };
int c[] = { 6,7,8 };
ptr[0] = a;
ptr[1] = b;
ptr[2] = c;
for (int i = 0;i < 3;i++)
printf("%d %d %d\n",*ptr[0]++,*ptr[1]++,*ptr[2]++);
return 0;
}
Answered in comments.
I updated the code to find top 5 indices of a float array. Some
how it is only updating top[0]th element for max indices. In the
mentioned example below max indices is like below top[0] = 9, top[1]
=7, top[2]=5 and so on. But it is updating top[0] only.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main() {
double *arr =malloc(sizeof(double)*10);
int N=10;
int n =5;
int *top =malloc(sizeof(int)*10);
arr[0] = 0.123;
arr[1] = 0.345;
arr[2] = 0.445;
arr[3] = 0.545;
arr[4] = 0.645;
arr[5] = 0.745;
arr[6] = 0.542;
arr[7] = 0.945;
arr[8] = 0.145;
arr[9] = 0.995;
int top_count = 0;
int i;
for (i=0;i<N;++i) {
// invariant: arr[top[0]] >= arr[top[1]] >= .... >= arr[top[top_count-1]]
// are the indices of the top_count larger values in arr[0],...,arr[i-1]
// top_count = max(i,n);
int k;
for (k=top_count;k>0 && arr[i]>arr[top[k-1]];k--);
// i should be inserted in position k
if (k>=n) continue; // element arr[i] is not in the top n
// shift elements from k to top_count
printf("6:: Iam here\n");fflush(stdout);
int j=top_count;
if (j>n-1) { // top array is already full
j=n-1;
} else { // increase top array
top_count++;
}
for (;j>k;j--) {
top[j]=top[j-1];
}
// insert i
top[k] = i;
printf("top[%0d] = %0d\n",k,top[k]);
printf("top_count=%0d\n",top_count);
}
return top_count;
}
int top_elems(double *arr, int N, int *top, int n);
int top_count = top_elems(&output, 10, top,5);
output already decomposes to double * do you are passing the address_ of a pointer to double into a function that should take a pointer to double
top is not initialised before the function call so is undefined the first use of it dereferences this undefined pointer
... yeah, I'm not going to go further. your code has some serious but simple to spot issues. If you had made a MCV example, you should have seen some of of them, instead of just dumping your code here.
After code changes:
I updated question to update the top five indices of float array into top[] array. but it is only updating top[0]th element. anything wrong with the code?
Well, I updated the indentation of the code in the question to make it more readable.
You will notice that there is no indentation after this for loop:
for (k=top_count;k>0 && arr[i]>arr[top[k-1]];k--);
This is because the loop body of this loop is:
;
That's it. it is just an empty statement that does nothing. All the loop does is set variables, which are then modified in the rest of the code that follows, but as they are not within a loop, they are only executed the once.
As the loop goes from top_count down to 0, it should be obvious why it is just the first index that is modified.
I have started an introductory class to C. I cannot explain the output that I get from running the code below
./a.out 6
Output is:
Array A elements: 0 1 2 3 4 5
Array B elements: 1 2 3 4 5 796830176
What I think the code is doing:
When manup_array is executed, each value of the respective pointers will be incremented, but since it is post-fix, this takes effect only later on after the original value is returned.
True enough, when we print array A first, we get 0 1 2 3 4 5 (i.e. before incrementation).
Subsequently when we print array B, the incrementation takes effect, so we get 1 2 3 [...]
What really puzzles me is why the last number is 796830176. Also, running this on various computers produces a different last number every time, suggesting that the pointer addressing is somehow responsible for this.
Could someone explain this to me?
Note:
The outputs of each array are identical (1 2 3 4 5 6) if I use the pre-fix operator. This is consistent with what I think is going on -> the pointers don't change; only the values get updated.
#include <stdio.h>
#include <stdlib.h>
void manup_array(int *array[], int n); // Forward declaration.
int main(int argc, char *argv[])
{
// The size N of 2 arrays are the same; obtain them from cmd line.
int N = atoi(argv[1]); // Convert from str to int in C.
int arrayA[N]; // Declare integer array.
int *arrayB[N]; // Declare integer pointer array.
for (int i = 0; i < N; i++)
{
arrayA[i] = i;
arrayB[i] = &arrayA[i]; // Assign address of each element in A to element in B.
}
manup_array(arrayB, N);
printf("Array A elements: ");
for (int i = 0; i < N; i++)
{
printf("%d ", arrayA[i]);
}
printf("\n");
printf("Array B elements: ");
for (int i = 0; i < N; i++)
{
printf("%d ", *arrayB[i]);
}
printf("\n");
return 0;
}
void manup_array(int *array[], int n) { // Take in B as input, then increase each elem by 1
for (int i = 0; i < n; i++)
{
*array[i]++;
}
}
This is really obscure code. What is does:
The function takes an array of pointers as parameter. Since the parameter to the function had type int *array[], any change of the items of array will affect the caller and alter arrayB.
The interesting part of the function is *array[i]++;. The operator precedence rules in C state that [] has higher prio than postfix ++, which has higher prio than unary *.
Since array is an array of pointers, array[i] gives you a pointer. Not a the value it points at. Then ++ increments the pointer to point at the next item in the arrayA of main.
And then finally there is a * which takes the contents of what that pointer pointed at, and then does nothing with them. The * is superfluous and just there to confuse the reader.
So back in main, you have changed all the pointers of arrayB. arrayB[0] now points at arrayA[1] and so on. The last item of arrayB will point one item past the end of arrayA, so for the last item, you access the array out-of-bounds and get a garbage value.
void manup_array(int *arr[], int n) { // Take in B as input, then increase each elem by 1
for (int i = 0; i < n; i++)
{
int val = (*arr[0]); // get the value pointed to by the current value of arr
val++; // increment it
*(arr[0]) = val; // assign it back
arr++; // increase the pointer
}
}
Incredibly obtuse, but it demonstrates what you mean to do and how your obscure code muddled up the operators.
To add, makes debugging way easier!
manup_array() increments the pointer, not the value as expected.
Modified manup_array().
void manup_array(int *array[], int n) { // Take in B as input, then increase each elem by 1
for (int i = 0; i < n; i++)
{
//*array[i]++;
(*array[i])++;
}
}
I suggest to refer Pointer Arithmetic: ++*ptr or *ptr++?
i have declared a pointer to a group of 3-d array which I have shared below.I have a problem in accessing elements of the 3-d array using pointers to the 3-d array.
#include <stdio.h>
void main()
{
int m,row,col;
int *ptr,*j;
int array[2][5][2]={10,20,30,40,50,60,70,80,90,100,18,21,3,4,5,6,7,81,9,11};
int (*p)[5][2]; // pointer to an group of 3-d array
p=array;
for(m=0;m<2;m++)
{
ptr=p+m;
for(row=0;row<5;row++)
{
ptr=ptr+row;
for(col=0;col<2;col++)
{
printf("\n the vale is %d",*(ptr+col));
}
}
}
}
output:
the value is 10
the value is 20
the value is 20
the value is 30
the value is 40
the value is 50
the value is 70
the value is 80
the value is 18
the value is 21
the value is 18
the value is 21
the value is 21
the value is 3
the value is 4
the value is 5
the value is 7
the value is 81
the value is -1074542408
the value is 134513849
my question is how to access the elements of 3-d array using pointer to an array and in my case the output shows my code not accessing the elements 90,100,9,11 and how do i can access this in the above code.Thanks in advance.
Although flattening the arrays and accessing them as 1-d arrays is possible, since your original question was to do so with pointers to the inner dimensions, here's an answer which gives you pointers at every level, using the array decay behaviour.
#include <stdio.h>
/* 1 */
#define TABLES 2
#define ROWS 5
#define COLS 2
/* 2 */
int main()
{
/* 3 */
int array[TABLES][ROWS][COLS] = {
{ {10, 20}, {30, 40}, {50, 60}, {70, 80}, {90, 100} },
{ {18, 21}, {3, 4}, {5, 6}, {7, 81}, {9, 11} }
};
/* pointer to the first "table" level - array is 3-d but decays into 2-d giving out int (*)[5][2] */
/* name your variables meaningully */
int (*table_ptr)[ROWS][COLS] = array; /* try to club up declaration with initialization when you can */
/* 4 */
size_t i = 0, j = 0, k = 0;
for (i = 0; i < TABLES; ++i)
{
/* pointer to the second row level - *table_ptr is a 2-d array which decays into a 1-d array */
int (*row_ptr)[COLS] = *table_ptr++;
for (j = 0; j < ROWS; ++j)
{
/* pointer to the third col level - *row_ptr is a 1-d array which decays into a simple pointer */
int *col_ptr = *row_ptr++;
for (k = 0; k < COLS; ++k)
{
printf("(%lu, %lu, %lu): %u\n", (unsigned long) i, (unsigned long) j, (unsigned long) k, *col_ptr++); /* dereference, get the value and move the pointer by one unit (int) */
}
}
}
return 0; /* report successful exit status to the platform */
}
Inline code comments elaborated with reference
It's good practise to have the dimensions defined commonly somewhere and use it elsewhere; changing at one place changes it at all places and avoids nasty bugs
main's retrun type is int and not void
It's recommended not to avoid the inner braces
Use size_t to hold size types
Problems in your code
For the line ptr=p+m;, GCC throws assignment from incompatible pointer type; reason is p is of type int (*)[5][2] i.e. pointer to an array (size 5) of array (size 2) of integers, which is assigned to ptr which is just an integer pointer. Intead if you change it to int (*ptr) [5]; and then do ptr = *(p + m);. This is what my code does (I've named p as table_ptr), only that it doesn't use m but it increments p directly.
After this at the third level (inner most loop), you need a integer pointer say int *x (in my code this is col_ptr) which you'd do int *x = *(ptr + m1). Bascially you need to have three different pointers, each for one level: int (*) [5][2], int (*) [2] and int *. I've named them table_ptr, row_ptr and col_ptr.
Rewritten your code below and just used the pointer p to print everything.
#include <stdio.h>
void main()
{
int m,row,col;
int array[2][5][2]={10,20,30,40,50,60,70,80,90,100,18,21,3,4,5,6,7,81,9,11};
int (*p)[5][2]; // pointer to an group of 3-d array
p=array;
for(m=0;m<2;m++)
{
for(row=0;row<5;row++)
{
for(col=0;col<2;col++)
{
printf("\n the vale is %d", *((int*)(p+m) + (row*2) + col));
}
}
}
}
You can easily access all the elements simply by a looping through 2*5*2 = 20 and using a pointer to the first element of array, i.e, array[0][0][0] assuming 3D array as 1D array of arrays of arrays of int's.
#include <stdio.h>
void main()
{
int m; //row,col;
int *ptr; //,*j;
int array[2][5][2]={10,20,30,40,50,60,70,80,90,100,18,21,3,4,5,6,7,81,9,11};
//int (*p)[5][2]; // pointer to an group of 3-d array
//p=array;
ptr = &array[0][0][0];
for(m=0;m <2;m++)
{
for (m = 0; m < 20; m++)
/* ptr=ptr+m;
for(row = 0;row < 5;row ++)
{
ptr=ptr+row;
for(col=0;col<2;col++)
{
printf("\n the vale is %d",*(ptr+col));
}
}*/
printf("\n the vale is %d", *(ptr++));
}
}
I commented some parts of your code and left it in the modified code to let you clear what I have done.
#include<stdio.h>
int main()
{
int array[2][2][2]={1,2,3,4,5,6,7,8};
int *p;
p=&array[0][0][0];
int i=0,j,k;
/*Accessing data using pointers*/
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
{
for(k=0;k<2;k++)
{
printf("%d\n",*p);
p++;
}
}
}
return 0;
}
This is a sample code where elements in a 2X2X2 array is been accessed using pointers.
Hope it helps !!!!