I'm unable to know why do we have to use typecasting (int *) in case of 2d array?
another thing I want to know is that why can't we use *(*(p+i)+j)) to access the 2d array in following code? Is it always necessary to use p + col*i + j? Why can't I use *(*(p+i)+j)) when p contains base address of array and *(*(p+i)+j)) is equivalent to a[i][j]?
Thank you in advance.
main()
{
int a[3][4] = {
1,2,3,4,
5,6,7,8,
9,0,1,6
};
int *p,i,j;
p=(int *)a; // this is my doubt why did we use int *
for(i=0;i<3;i++)
{
for(j=0;j<4;j++) {
printf("%d",*(*(p+i)+j)); // here is my 2nd doubt
}
}
}
The code you provided does not compile because of line:
printf("%d",*(*(p+i)+j));
where you are dereferencing twice an int*
You can create a pointer to reference the array a of type pointer to array of 4 elements.
See the attached code where are all pointers are printed out during the execution of the nested for loop.
#include<stdio.h>
main()
{
int a[3][4]={
1,2,3,4,
5,6,7,8,
9,0,1,6
};
int (*p)[4],i,j;
p = a;
for(i=0;i<3;i++){
printf("row pointer: %p\n",p+i);
for(j=0;j<4;j++){
printf("element pointer: %p\n", (*(p+i))+j );
printf("element: %d\n",*( (*(p+i)) + j ) );
}
}
}
Your code does not even compile, exactly where your 2nd place of doubt is. I've corrected it:
#include <stdio.h>
int main(int argc, char *argv[])
{
int a[3][4] = {
1,2,3,4,
5,6,7,8,
9,0,1,6,
};
int *p, i, j;
p = a[0]; // No cast, just address the 1st row
for (i = 0; i < 3; i++) {
for (j = 0; j < 4; j++) {
printf("%d", *(p + 4*i + j)); // corrected pointer arithmetic
}
}
}
Pointer p does not know it's addressing a 2-dim array, it's just an int pointer.
Are you sure you want to print the numbers without even separating them by whitespace?
Related
I just started to tinker with pointers in multidimensional arrays and was trying to pass and array into a void function. The compilator just threw an error. I need the array to be passed exactly as a pointer to maybe change it then by reference.
#include <stdio.h>
#include <stdlib.h>
void Func(int** matrix, int sizeFirst, int sizeSecond)
{
for (int i = 0; i < sizeFirst; i++)
{
for (int j = 0; j < sizeSecond; j++)
{
printf("%d\n", matrix[i][j]);
}
}
}
int main()
{
int array[2][3] = {
{5,8,2},
{1,3,6}
};
int sizeMain = sizeof(array)/sizeof(array[0]);
int sizeInner = sizeof(array[0])/sizeof(array[0][0]);
Func(array, sizeMain, sizeInner);
return 0;
}
2D array is not pointer to pointer. Your code is invalid as Func does not know how many columns every row has. Also, use the correct type for sizes & indexes
void Func(size_t sizeFirst, size_t sizeSecond, int (*matrix)[sizeSecond])
{
for (int i = 0; i < sizeFirst; i++)
{
for (int j = 0; j < sizeSecond; j++)
{
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
int main()
{
int array[2][3] = {
{5,8,2},
{1,3,6}
};
size_t sizeMain = sizeof(array)/sizeof(array[0]);
size_t sizeInner = sizeof(array[0])/sizeof(array[0][0]);
Func(sizeMain, sizeInner, array);
return 0;
}
https://godbolt.org/z/Ejfrdd3nK
With pointers to VLAs, you can preserve all of the dimensions in the type of the argument and then let C do the multidimensional scaling for you.
In older versions of C you need to calculate the spot manually, remembering that
the first dimension from the right moves by 1 (scaled by sizeof(type), which C does for you), the second by first dimension from the right,
the third by first dimension from the right multiplied by second dimension from the right and so on.
It's sort of like digits in numbers (units, tens, hundreds, ...) except that the next scaling is the previous scaling multiplied by the previous dimension rather than by a constant radix.
(You could let C convert groups of decimal digits to decimal numbers by letting it subtract some &decdigits[a][b][c] and &decdigits[0][0][0] where decdigits is some decdigits[10][10][10], i.e.:
char decdigits[10][10][10]; printf("%d\n", (int)(&decdigits[1][2][3] - &decdigits[0][0][0])) /*prints 123*/;)
#include <stdio.h>
void Func( int sizeFirst, int sizeSecond, int (*matrix)[sizeFirst][sizeSecond])
{
for (int i = 0; i < sizeof((*matrix))/sizeof((*matrix)[0]) ; i++)
{
for (int j = 0; j < sizeof((*matrix)[0])/sizeof((*matrix)[0][0]) ; j++)
{
printf("%d ", (*matrix)[i][j]);
}
puts("");
}
}
void Func_89( int sizeFirst, int sizeSecond, int *matrix)
{
for (int i = 0; i < sizeFirst; i++)
{
for (int j = 0; j < sizeSecond; j++)
{
printf("%d ", matrix[i*sizeSecond + j]);
}
puts("");
}
}
int main()
{
int array[2][3] = {
{5,8,2},
{1,3,6}
};
int sizeMain = sizeof(array)/sizeof(array[0]);
int sizeInner = sizeof(array[0])/sizeof(array[0][0]);
Func(sizeMain, sizeInner,&array );
puts("===");
Func_89(sizeMain, sizeInner,&array[0][0] );
//char decdigits[10][10][10]; printf("%d\n", (int)(&decdigits[1][2][3] - &decdigits[0][0][0])); //123
return 0;
}
First of you have to understand what int ** represent, it represents pointer to integer pointer, here's an example:
int a = 10;
int *p = &a; // 'p' points to 'a`
int **pp = &p; // 'pp' points to 'p' (pointer to integer)
So because of this, you can't use int ** for an integer array. Now that's out of the way, let's see what can you do instead (solution)
You can simply add a pointer to an integer array in a function definition like this
void Func(int *matrix[], int rows, int cols)
Or you can simply do
void Func(int matrix[rows][cols])
Note: Array of strings or 2D character array (char array[][]) can be represented as char**
I'm really having a difficult time understanding how to pass the address of a 2D array of char pointers to a function, and actually assigning a value to it.
void fillWithStrings( 'pointer to foo' ){ // How to do this part?
for( int i = 0; i < SIZE; i++ ) {
for( int j = 0; j < SIZE; j++ ) {
char * temp = malloc( sizeof(char) * 3 );
temp = "hi";
*foo[i][j] = temp; // And this part?
}
}
}
int main(){
char * foo[SIZE][SIZE];
fillWithStrings( &foo );
return 0;
}
And yes, it is easier to fill foo in the scope where it was declared, but the point is, how to do it inside another function?
There is no need to pass the address of foo to fillWithStrings(), as the function does not want to change the value of foo (which, BTW, wouldn't even be possible as foo is an array).
Just pass foo, which then would decay to a pointer to is 1st element. It's 1st element is a char * [SIZE], the address to the latter is char * (*) [SIZE].
Code doing so might look like this:
#include <stdio.h>
#include <stdlib.h>
#define SIZE (7)
int array_init(char * (*a)[SIZE])
{
for (size_t i = 0; i < SIZE; ++i)
{
for (size_t j = 0; j < SIZE; ++j)
{
a[i][j] = calloc(42, sizeof *(a[i][j])); /* Allocate 42 times the size of
what (a[i][j]) points , that is a char.*/
if (NULL == a[i][j])
{
return -1;
}
}
}
return 0;
}
int main(void)
{
char * a[SIZE][SIZE] = {0};
if (-1 == array_init(a))
{
perror("array_init() failed");
exit(EXIT_FAILURE);
}
/* Do stuff. */
/* Free a's elements here. */
return EXIT_SUCCESS;
}
First of all, there is no such thing as passing by reference in C. Everything is passed by value. An array is "passed" as pointer to its first element. This pointer is also passed by value. It is being copied as function argument, but the array that it points at is left as it is, and can be seen from your function.
char * foo[SIZE][SIZE] is a two-dimensional array of character pointers. These pointers may point to charactres or arrays of characters. Since there is no specifiation of the size of these arrays of characters, from your code fillWithStrings() it can be assumed that these arrays are intended to be \0 terminated strings of characters.
Running this demonstration code may help better understand what is going on in your function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 4
void fillWithStrings( char* (foo)[SIZE][SIZE] ){
for( int i = 0; i < SIZE; i++ ) {
for( int j = 0; j < SIZE; j++ ) {
char * temp = malloc( 3 ); //sizeof(char) is always 1
if (j % 2) strcpy(temp, "lo");
else strcpy(temp,"hi");
foo[i][j] = temp;
}
}
}
int main(){
char * foo[SIZE][SIZE];
fillWithStrings( foo );
for( int i = 0; i < SIZE; i ++)
for (int j = 0; j < SIZE; j++)
printf("[%d][%d] = %s\n", i, j, foo[i][j]);
return 0;
}
For the first part the replace 'pointer to foo' with char* (*foo)[SIZE][SIZE]
This breaks down as follows:
(*foo) means foo is a pointer to something,
(*foo)[SIZE][SIZE] means foo points to a 2D array of somethings,
char* (*foo)[SIZE][SIZE] means foo points to a 2D array of pointers to char.
The use of the parentheses is necessary to avoid this being interpreted as a 2D array of pointers to pointers to char.
For the second part, (*foo)[i][j] = temp;
(*foo) will get the original array foo points to and
(*foo)[i][j] specifies where in that array the assignment will go.
EDIT: fixed second part and added explanations
This should work:
typedef char *FOO_TYPE [SIZE][SIZE]; // Or whatever your size/name is
void fillWithStrings (FOO_TYPE& foo)
{
}
You can then use it exactly as if it were declared locally.
i've tried searching for the answer/ looking at the C library for pointers, but wasn't sure on the right solution. My question concerns changing the parameters of a function. I've been reading on pointers/functions, and from my understanding, if a function takes in (int x1), then when the function is done with x1, x1 outside the function remains untouched. However, if you pass in a int *x1, then it is changed.
I've been experimenting with it, and i've tried using this with a sort method...
void sorting(int *arr, int size) {
int *i, *j, temp;
int *len = arr + size - 1;
for(i = arr; i < len; i++) {
for(j = i + 1; j <= len; j++) {
if(*j < *i) {
temp = *i;
*i = *j;
*j = temp;
}
}
}
int k;
for(k = 0; k < size; k++) {
printf("k: %d, arr[k]: %d \n", k, *(arr + k));
}
}
What this would print is a fully sorted list. However, in my main function, if I called this...
int main() {
int temp[5] = {0, 2, 1, 3, 1};
int *p = &temp[5];
sorting(pa, 5);
print the values of pa...
}
Then the list remains unsorted if printing out the values of pa.
If this question has already been solved, could someone please link the question, and i'll delete the post.
You're accessing the array out of bounds here:
int *p = &temp[5];
The valid indices are [0, 5). Presumably you want a pointer to the first element:
int *p = &temp[0];
But note that you can pass an array to a function that expects a pointer. In this case the array decays to a pointer to the first element:
sorting(temp, 5);
I'm practicing pointers and want to substitute pointer operations in place of the arrays to traverse through the elements of the array. I have read numerous articles and cannot grasp this concept. Can someone explain?
Here I made a 2D array and iterated through it using a basic nested for-loop, but want to use pointers;
int test[3][2] = {1,4,2,5,2,8};
for (int i = 0 ; i < 3; i++) {
for (int j = 0; j < 2; j++) {
printf("%d\n", test[i][j]);
}
}
int test[3][2] = {{1,4},{2,5},{2,8}};
// Define a pointer to walk the rows of the 2D array.
int (*p1)[2] = test;
// Define a pointer to walk the columns of each row of the 2D array.
int *p2 = NULL;
// There are three rows in the 2D array.
// p1 has been initialized to point to the first row of the 2D array.
// Make sure the iteration stops after the third row of the 2D array.
for (; p1 != test+3; ++p1) {
// Iterate over each column of the arrays.
// p2 is initialized to *p1, which points to the first column.
// Iteration must stop after two columns. Hence, the breaking
// condition of the loop is when p2 == *p1+2
for (p2 = *p1; p2 != *p1+2; ++p2 ) {
printf("%d\n", *p2);
}
}
In some compilers you can also use a single loop, treating a multidimensional array as a one-dimensional array read in row-major order.
This is mentioned in King's C Programming: A Modern Approach (2nd ed., p268).
#include <stdio.h>
int main(void)
{
int test[3][2] = {{1,4},{2,5},{2,8}}, *p;
for(p = &test[0][0]; p <= &test[2][1]; p++)
{
printf("%d\n", *p);
}
return 0;
}
Try the following and investigate
#include <stdio.h>
int main(void)
{
int test[3][2] = { { 1,4 }, { 2,5 }, { 2,8 } };
for ( int ( *p )[2] = test ; p != test + 3; ++p )
{
for ( int *q = *p; q != *p + 2; ++q ) printf( "%d ", *q );
puts( "" );
}
return 0;
}
The putput is
1 4
2 5
2 8
The first pointer is a pointer to an object of type int[2] that is it points to the first "row" of the array and then due to increments it points to other rows.. The second pointer is a pointer to an object of type int. It points to the first element of each row in the inner loop.
Treating a 2d array as 1d array is very easy using pointer arithmetic to iterate.
void print_2d_array(int *num, size) {
int counter = 0;
while (counter++ < size) {
printf("%i ", *num);
num++;
}
printf("\n");
}
int main() {
int matrix[2][3] = {{2, 11, 33},
{9, 8, 77}};
int matrix_size = sizeof(matrix) / sizeof(int); // 24 bytes / 4 (int size) = 6 itens
print_2d_array(matrix, matrix_size);
return 0;
}
If pointer declaration is the goal of your practice, use the following initialization:
int (*pTest)[rmax][cmax] = test;
Once you do that, the syntax of using pointer indexing mirrors that of array indexing, except that you have to use the * de-referencing operator.
for (int i= 0; i < 3; i++) {
for (int j= 0; j < 2; j++) {
printf ("%d ", *(pTest[i][j]));
}
printf ("\n");
}
However, if pointer arithmetic is the goal of your practice, then the following will work too:
int *res = &test;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
printf ("%d ", *(res + i*2 + j));
}
printf ("\n");
}
OUTPUT
1 4
2 5
2 8
How to find number of rows in dynamic 2D char array in C?
Nothing from there.
tried with following code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int k = 97;
void foo(char **a)
{
int i = 0;
for(i=0; a[i] != NULL; ++i)
printf("i = %d\n", i);
}
void strcpyo(char* a, char*b){
int i=0;
for(i=0;b[i]!='\0';i++){
a[i]=b[i];
}
a[i]='\0';
}
void strcpym(char* a, char*b){
int i=0;
for(i=0;b[i]!='\0';i++);
memcpy(a,b,i+1);
}
void freee(char** ptr){
int i;
for(i = 0;i < k; ++i)
{
free(ptr[i] );
}
free(ptr);
}
void alloc(char ***p)
{
*p = (char **)malloc(k * sizeof(char *));
int i,j;
for(j=0;j<k;j++)
{
// for(i = 0;i < j; ++i)
{
(*p)[j] = (char *)malloc(11 * sizeof(char));
strcpy((*p)[j],"paicharan");
}
//printf("j = %d ", j);
//foo(p);
}
}
int main()
{
char **p;
alloc(&p);
#if 0
char **p = (char **)malloc(k * sizeof(char *));
int i,j;
for(j=0;j<k;j++)
{
for(i = 0;i < j; ++i)
{
p[i] = (char *)malloc(11 * sizeof(char));
strcpy(p[i],"paicharan");
}
printf("j = %d ", j);
foo(p);
}
#endif
foo(p);
freee(p);
return 0;
}
The code in #if 0 #endif works perfectly, but if I do create arrays in function alloc(char**) it's giving the wrong answer for odd number of rows in array. Can anybody explain why?
ie. for k= odd number it gives out wrong answer but for even number its correct.
Your code depends on Undefined Behaviour to work correctly i.e. it'll work only by chance. This has got nothing to do with even or odd count of elements.
In the void alloc(char ***p) function you allocate memory for k pointer to pointer to char: char**. Then you fill all of the k pointers with new valid char* pointers i.e. none of them are NULL. Later in void foo(char **a) you do for(i=0; a[i] != NULL; ++i); since a[k - 1] was non-null, it'll iterate over them correctly. BUT after that a[k] may or may not be NULL, you never know what is in there. Also accessing what is beyond the array you allocated is undefined behaviour (due to out of bounds access).
Making k + 1 elements and setting the kth element to NULL makes this work; make sure you free all of k + 1 elements and not leak the last sentinal element.
Since you told that the code wraped inside the macro works fine, I've ignored that; don't know if there's UB there too. If you're doing this exercise to learn, it's fine. If you are planning to do some other project, try to reuse some existing C library which already gives these facilities.