expected expression ,what is expected here - c

int **A;
A=(int**)malloc(3*sizeof(int*));
A[0]=(int *)malloc(4*sizeof(int));
A[1]=(int *)malloc(4*sizeof(int));
A[2]=(int *)malloc(4*sizeof(int));
A[3][4]={{1,2,3,4},{1,2,3,4},{1,2,3,4}};
for(int i=0;i<3;i++)
{
for(int j=0;j<4;j++)
printf("%d ",A[i][j]);
printf("\n");
}
}
Here it is showing that "expected expression" what should I do please help me out.

For starters bear in mind that it is not a good style of programming to use uppercase letters for identifiers of variables.
In this statement
A[3][4]={{1,2,3,4},{1,2,3,4},{1,2,3,4}};
you are trying to assign values in the braced list to the scalar object of the type int that even does not exists because the indices 3 and 4 access memory outside the dynamically allocated arrays.
So as the above expression statement uses the assignment operator then the compiler expects that the right operand of the assignment is an expression. Braced lists are not expressions. So the compiler issues an error.
Pay attention to that arrays do not have the assignment operator. You need to copy elements of one array into another or set elements individually.
You could initially declare an array and initialize it with the braced list like
int A[3][4]={{1,2,3,4},{1,2,3,4},{1,2,3,4}};
As for dynamically allocated arrays then you could initialize their elements in for loops like for example
for ( size_t i = 0; i < 3; i++ )
{
int value = 1;
for ( size_t j = 0; j < 4; j++ )
{
A[i][j] = value++;
}
}
Another approach is to use compound literals like
for ( size_t i = 0; i < 3; i++ )
{
memcpy( A[i], ( int[] ){ 1, 2, 3, 4 }, sizeof( int[4] ) );
}
Here is a demonstration program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( void )
{
enum { M = 3, N = 4 };
int **a = malloc( sizeof( int *[M] ) );
for ( size_t i = 0; i < M; i++ )
{
a[i] = malloc( sizeof( int[N] ) );
memcpy( a[i], ( int[N] ){ 1, 2, 3, 4 }, sizeof( int[N] ) );
}
for ( size_t i = 0; i < M; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
printf( "%d ", a[i][j] );
}
putchar( '\n' );
}
for ( size_t i = 0; i < M; i++ )
{
free( a[i] );
}
free( a );
}
The program output is
1 2 3 4
1 2 3 4
1 2 3 4
In general you should check whether memory was allocated successfully.

I see no reason to do more than one malloc here (and perhaps not even that one).
In the below you try to assign all values to one single element in the 2D array (and it's also out of bounds since A[2][3] is the last accessible element).
A[3][4]={{1,2,3,4},{1,2,3,4},{1,2,3,4}}
What you could do is to memcpy instead.
Example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int(*A)[4] = malloc(3 * sizeof *A); // only one allocation
// "assign" all values to where A points:
memcpy(A, (int[3][4]){{1, 2, 3, 4},{1, 2, 3, 4},{1, 2, 3, 4}}, 3 * sizeof *A);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) printf("%d ", A[i][j]);
printf("\n");
}
free(A); // only one deallocation
}

A[3][4]={{1,2,3,4},{1,2,3,4},{1,2,3,4}};
It is definitely wrong.
you can assign the pointer element of the allocated array with reference to the existing array or compound literal. But it will not possible to use it as 2D array as per your pseudo code, only 1D array.
A[3]=(int[]){1,2,3,4,5,6,7,8,9,0};
or
int B[] = {1,2,3,4,5,6,7,8,9,0};
A[3] = B;
A[3] is out of bounds so you need to change the malloc as well.
A = malloc(4 * sizeof(*A));
Also do not cast the result of malloc. If your code does not compile, it means that you are using C++ compiler to compile C code which is not correct

A[3][4]={{1,2,3,4},{1,2,3,4},{1,2,3,4}}; is wrong. I think you are trying to assign something to the whole array. There are at least three things wrong with that:
Arrays cannot be assigned to like that. The syntax you used is for initialization (as part of a declaration), not assignment (as part of an expression statement).
A is not a 2-D array of int, it is a dynamically allocated array of int * whose elements point to (the first elements of) dynamically allocated arrays of int.
In an expression, A[3][4] refers to a single int element. You can only assign a value of scalar type to it. Also, both the first index 3 and the second index 4 are out of range for array access; they both refer to an element one past the last element of the the array at the corresponding dimension. Taking the address of the element one past the last element is allowed, but accessing that element is not allowed.
The elements need to be assigned individually (or via memcpy), for example using a couple of for loops:
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
A[i][j] = j + 1;
}
}
If A was an actual 2-D array of int, it could be declared and initialized using an initializer:
int A[3][4]={{1,2,3,4},{1,2,3,4},{1,2,3,4}};

Related

Printing a multidimensional array in C

I am trying to print a 2-D array in C by using pointers but I am not getting the expected output.
Program:-
#include <stdio.h>
int main()
{
int arr[2][3] = {{1,2,3},{4,5,6}};
int* p;
for ( p = arr; p <= arr+6; p++)
{
printf("%d ", *p);
}
return 0;
}
Output:-
1 2 3 4 5 6 -1116112128 1587637938 0 0 1893963109 32521 -1453950296 32766 -1453805568 1 800797033 21984 -1453949463
Could you tell me where I am wrong as the output should only be:
1 2 3 4 5 6
Could you tell me where I am wrong
The elements of arr are not integers, but arrays of 3 integers. So arr+6 is surely a different address than what you expect, since pointer arithmetic works in multiples of the size of the type in the array.
You'll always be better off using nested loops to iterate over a multidimensional array; treating it as one single-dimensional array of int leads to exactly the kinds of confusion you see here. The code is harder to understand and verify, it won't be any slower.
First, when looping through arrays of size n wth an index i, the condition for continuation should be i < n rather than i <= n, because array indexes in C run from 0 through n-1.
However, your code has a more serious error: 1-dimensional arrays can be 'decayed' into pointers to the elements' type; however, 2-dimensional arrays decay into pointers to 1-dimensional arrays. So, in your case, the type of the pointer used in the arr + 6 expression is a pointer to an array of three integers; further, when the 6 is added, that operation is performed in terms of the size of the pointed-to object, which is sizeof(int) * 3 – so, even when changing the <= to <, you will be running far beyond the actual bounds of the array.
To make the pointer arithmetic work in the correct 'units' (i.e. sizeof(int)), cast the arr to an int* before the addition (and also change the <= to <):
#include <stdio.h>
int main()
{
int arr[2][3] = { {1,2,3},{4,5,6} };
int* p;
for (p = (int*)arr; p < (int*)arr + 6; p++) {
printf("%d ", *p);
}
return 0;
}
You are trying to access the value in the wrong way, The two-dimensional array is saved as a continuous block in the memory. So, if we increment the value of ptr by 1 we will move to the next block in the allocated memory.
int arr[2][3] = {{1,2,3},{4,5,6}};
int *ptr = arr;
int i,j;
for (i = 0; i < 6; i++) {
printf("%d ", *(ptr + i));
}
return 0;
Array designators used in expressions with rare exceptions are implicitly converted to pointers to their first elements.
The type of the array elements of this array
int arr[2][3];
is int [3]. So a pointer to the first element of the array has the type int ( * )[3].
This assignment
p = arr;
where p has the type int * is incorrect because the operands of the assignment have incompatible pointer types.
At least you need to cast the right expression to the type int * like
p = ( int * )arr;
The same casting you need to use in the condition in the for loop. That is instead of
p <= arr+6
you have to write
p < ( int * )arr+6
Below there is a demonstration program that shows how to output a two-dimensional array as a two-dimensional array using pointers.
#include <stdio.h>
int main( void )
{
int arr[2][3] = {{1,2,3},{4,5,6}};
for ( int ( *p )[3] = arr; p != arr + 2; p++ )
{
for ( int *q = *p; q != *p + 3; ++q )
{
printf( "%d ", *q );
}
putchar( '\n' );
}
return 0;
}
If you want to output the two-dimensional array as a one-dimensional array then you can write
#include <stdio.h>
int main( void )
{
int arr[2][3] = {{1,2,3},{4,5,6}};
for ( int *p = ( int * )arr; p != ( int * )arr + 6; p++ )
{
printf( "%d ", *p );
}
putchar( '\n' );
return 0;
}
In
for ( p = arr; p <= arr+6; p++)
the expression arr, as an rvalue, is a pointer to the first element of the array (which is of type int [3], so each time you increment that pointer, it moves three int positions forward ---a whole row---, and so, arr + 6 points just after the sixth row of the array (if the array should ever had six rows) You can do it (with the proper explicit pointer conversions, as you are mixing pointers to int with pointers to int [3]) with the expression arr + 2 which is the addres of the first array element after the second row (and the number of rows of the array).
You can do it also declaring
int (*aux)[2][3] = &arr; /* aux is a pointer to the whole 3x2 array,
* so aux + 1 will be the position of the second
* 2D array after this one */
and then
int *end = (int *)(aux + 1);
or simply
int *end = (int *)(&arr + 1); /* see below */
(Beware that arr and &arr are both pointers and point to the same place, but they are not the same type (arr is of type int (*)[3] and &arr is of type int(*)[2][3])
So let's rewrite your code as
for (p = (int *)arr; p < end; p++)
or
for (p = (int *)arr; p < (int *)&arr + 1; p++)
would work, which seems more natural to do the calculus in complete array units than in rows or single cells (and you can change freely the dimensions of the array)
Your code would be:
#include <stdio.h>
int main()
{
int arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
int *end = (int *)(&arr + 1); /* try to avoid evaluating this expression in the loop
* despite that it can be optimized to comparing
* with a constant value */
char *sep = "";
for (int *p = (int *)arr; p < end; p++)
{
printf("%s%d", sep, *p);
sep = ", ";
}
putchar('\n');
return 0;
}
(Beware that you have to use < operator and not <= as you don't want to print the value pointed by end, because it lies one place outside of the array)
Finally a note: this will work with true arrays, but not with function parameters declared as arrays, because they decay to pointers and then &arr is not a pointer to data the size of the array, but it is the address of the parameter itself, which points to the array somewhere else.

Use of a function on a 2d array

I have written code which allows me to modify the elements of a 1D array within my function by passing the element of the array:
I print the original array
I pass each element of the array to the function
Within the function I add the value 50 to each element of the array
I then call the function, and print out to screen the modified element value (i.e the value of each element +50)
I have been able to do this for a 1D array, with example values in the array being (10,20,30) and the valued printed after modification being (60,70,80).
What I am hoping to do is adapt that code to work for 2D arrays, you will see my attempt at doing this below. This code focuses on the use of int, but once I understand how to achieve this I am hoping to adapt for the use of a 2D string as well.
With the code below:
My objective is
Print to screen the original 2D array
Pass each element of the 2D array to the function
Within the function add the value 50 to each element of the array
Then call the function, and print out the modified element values to the screen(expected result displayed on screen 60,61,etc,.)
So far I have been able to print the original 2D array to the screen. It is the function I think I am messing up and would appreciate any advice. Thank you.
#include <stdio.h>
#include <string.h>
#define M 4
#define N 2
int function(int **arr);
int main() {
int i, a;
int arr[N][M] = {10, 11, 12, 13, 14, 15, 16, 17};
// the int array first
for(i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
// Accessing each variable
printf("value of arr[%d] is %d\n", i, arr[i][j]);
}
}
printf("\n ***values after modification***\n");
a = function(&arr[i][0]);
// int array print results
for(int i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
printf("value of arr %d\n", arr[i][j]);
}
}
return 0;
}
int function(int **arr) {
int i;
int j;
for(int i = 0; i < 3; i++) {
for(size_t j = 0; j < 5; j++) {
arr[i][j] = arr[i][j] + 50;
}
}
}
My apologies in advance for silly mistakes I am very new to C.
Thank you in advance.
The function int function(int **arr) does not return an int so make it void.
When you call it, a = function(&arr[i][0]);, you do not use a after the assignment. I suggest that you remove a from the program completely since it's not used anywhere.
The call to the function, function(&arr[i][0]);, should simply be function(arr);
The function signature needs to include the extent of all but the outermost dimension:
void function(int arr[][M])
Inside the function, you use 3 and 5 instead of N and M. That accesses the array out of bounds.
In function, the i and j you declare at the start of the function are unused. Remove them.
arr[i][j] = arr[i][j] + 50; is better written as arr[i][j] += 50;
When initializing a multidimensional array, use braces to make it simpler to read the code:
int arr[N][M] = {{10, 11, 12, 13}, {14, 15, 16, 17}};
In main you mix int and size_t for the indexing variables. I suggest you settle for one type.
Remove unused header files (string.h)
Example:
#include <stdio.h>
#define N 2
#define M 4
void function(int arr[][M]) {
for(int i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
arr[i][j] += 50;
}
}
}
int main() {
int arr[N][M] = {{10, 11, 12, 13}, {14, 15, 16, 17}};
for(size_t i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
printf("value of arr[%zu][%zu] is %d\n", i, j, arr[i][j]);
}
}
printf("\n ***values after modification***\n");
function(arr);
// int array print results
for(size_t i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
printf("value of arr[%zu][%zu] is %d\n", i, j, arr[i][j]);
}
}
}
Since you print the array more than once, you could also add a function to do so to not have to repeat that code in main:
void print(int arr[][M]) {
for(size_t i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
printf("value of arr[%zu][%zu] is %d\n", i, j, arr[i][j]);
}
}
}
Two-Dimensional arrays in C (and C++) are actually one-dimensional arrays whose elements are one-dimensional arrays. The indexing operator [] has left-to-right semantics, so for a type arr[N][M] the first index (with N elements) is evaluated first. The resulting expression, e.g. arr[0], the first element in arr, is a one-dimensional array with M elements. Of course that array can be indexed again , e.g. arr[0][1], resulting in the second int in the first sub-array.
One of the quirks in the C language is that if you use an array as a function argument, what the function sees is a pointer to the first element. An array used as an argument "decays" or, as the standard says, is "adjusted" that way. This is no different for two-dimensional arrays, except that the elements of a two-dimensional array are themselves arrays. Therefore, what the receiving function gets is a pointer to int arr[M].
Consider: If you want to pass a simple integer array, say intArr[3], to a function, what the function sees is a pointer to the first element. Such a function declaration might look like void f(int *intPtr) and for this example is simply called with f(intArr). An alternative way to write this is void f(int intPtr[]). It means exactly the same: The parameter is a pointer to an int, not an array. It is pointing to the first — maybe even only — element in a succession of ints.
The logic with 2-dimensional arrays is exactly the same — except that the elements, as discussed, have the type "array of M ints", e.g. int subArr[M]. A pointer argument to such a type can be written in two ways, like with the simple int array: As a pointer like void f(int (*subArrPtr)[M]) or in array notation with the number of top-level elements unknown, like void f(int arr[][M]). Like with the simple int array the two parameter notations are entirely equivalent and interchangeable. Both actually declare a pointer, so (*subArrPtr)[M] is, so to speak, more to the point(er) but perhaps more obscure.
The reason for the funny parentheses in (*subArrPtr)is that we must dereference the pointer first in order to obtain the actual array, and only then index that. Without the parentheses the indexing operator [] would have precedence. You can look up precedences in this table. [] is in group 1 with the highest priority while the dereferencing operator * (not the multiplication!) is in group 2. Without the parentheses we would index first and only then dereference the array element (which must therefore be a pointer), that is, we would declare an array of pointers instead of a pointer to an array.
The two possible, interchangeable signatures for your function therefore are
void function( int (*arrArg)[M] ); // pointer notation
void function( int arrArg[][M] ); // "array" notation (but actually a pointer)
The entire program, also correcting the problems Ted mentioned, and without printing the original values (we know them, after all), is below. I have also adapted the initialization of the two-dimensional array so that the sub-arrays become visible. C is very lenient with initializing structures and arrays; it simply lets you write consecutive values and fills the elements of nested subobjects as the come. But I think showing the structure helps understanding the code and also reveals mistakes, like having the wrong number of elements in the subarrays. I have declared the function one way and defined it the other way to show that the function signatures are equivalent. I also changed the names of the defines and of the function to give them more meaning.
#include<stdio.h>
#define NUM_ELEMS_SUBARRAY 4
#define NUM_ELEMS_ARRAY 2
/// #arrArg Is a pointer to the first in a row of one-dimensional
/// arrays with NUM_ELEMS_SUBARRAY ints each.
void add50ToElems(int arrArg[][NUM_ELEMS_SUBARRAY]);
int main()
{
// Show the nested structure of the 2-dimensional array.
int arr[NUM_ELEMS_ARRAY][NUM_ELEMS_SUBARRAY] =
{
{10, 11, 12, 13},
{14, 15, 16, 17}
};
// Modify the array
add50ToElems(arr);
// print results
for (int i = 0; i < NUM_ELEMS_ARRAY; i++) {
for (int j = 0; j < NUM_ELEMS_SUBARRAY; j++)
{
printf("value of arr[%d][%d]: %d\n", i, j, arr[i][j]);
}
}
return 0;
}
// Equivalent to declaration above
void add50ToElems(int (*arrArg)[NUM_ELEMS_SUBARRAY])
{
for (int i = 0; i < NUM_ELEMS_ARRAY; i++)
{
for (size_t j = 0; j < NUM_ELEMS_SUBARRAY; j++)
{
//arrArg[i][j] = arrArg[i][j] + 50;
arrArg[i][j] += 50; // more idiomatic
}
}
}
Why is it wrong to pass a two-dimensional array to a function expecting a pointer-to-pointer? Let's consider what void f(int *p) means. It receives a pointer to an int which often is the beginning of an array, that is, of a succession of ints lying one after the other in memory. For example
void f(int *p) { for(int i=0; i<3; ++i) { printf("%d ", p[i]); }
may be called with a pointer to the first element of an array:
static int arr[3];
void g() { f(arr); }
Of course this minimal example is unsafe (how does f know there are three ints?) but it serves the purpose.
So what would void f(int **p); mean? Analogously it is a pointer, pointing to the first in a succession of pointers which are lying one after the other in memory. We see already why this will spell disaster if we pass the address of a 2-dimensional array: The objects there are not pointers, but all ints! Consider:
int arr1[2] = { 1,2 };
int arr2[2] = { 2,3 };
int arr3[2] = { 3,4 };
// This array contains addresses which point
// to the first element in each of the above arrays.
int *arrOfPtrToStartOfArrays[3] // The array of pointers
= { arr1, arr2, arr3 }; // arrays decay to pointers
int **ptrToArrOfPtrs = arrOfPtrToStartOfArrays;
void f(int **pp)
{
for(int pi=0; pi<3; pi++) // iterate the pointers in the array
{
int *p = pp[pi]; // pp element is a pointer
// iterate through the ints starting at each address
// pointed to by pp[pi]
for(int i=0; i<2; i++) // two ints in each arr
{
printf("%d ", pp[pi][i]); // show double indexing of array of pointers
// Since pp[pi] is now p, we can also say:
printf("%d\n", p[i]); // index int pointer
}
}
}
int main()
{
f(ptrToArrOfPtrs);
}
f iterates through an array of pointers. It thinks that the value at that address, and at the subsequent addresses, are pointers! That is what the declaration int **pp means.
Now if we pass the address of an array full of ints instead, f will still think that the memory there is full of pointers. An expression like int *p = pp[i]; above will read an integer number (e.g., 1) and think it is an address. p[i] in the printf call will then attempt to access the memory at address 1.
Let's end with a discussion of why the idea that one should pass a 2-dimensional array as a pointer to a pointer is so common. One reason is that while declaring a 2-dimensional array argument as void f(int **arr); is dead wrong, you can access the first (but only the first) element of it with e.g. int i = **arr. The reason this works is that the first dereferencing gives you the first sub-array, to which you can in turn apply the dereferencing operator, yielding its first element. But if you pass the array as an argument to a function it does not decay to a pointer to a pointer, but instead, as discussed, to a pointer to its first element.
The second source of confusion is that accessing elements the array-of-pointers uses the same double-indexing as accessing elements in a true two-dimensional array: pp[pi][i] vs. arr[i][j]. But the code produced by these expressions is entirely different and spells disaster if the wrong type is passed. Your compiler warns about that, by the way.

How to use pointer to bidimensional array C

How do I edit a value in an array with pointer in C?
int *pointer;
int array[3][1];
I tried this:
int *Pointer
int array[2][2];
Pointer[1][1]= 6;
but when compiling, I get a segmentation fault error. What to do?
Given some array int Array[Rows][Columns], to make a pointer to a specific element Array[r][c] in it, define int *Pointer = &Array[r][c];.
Then you may access that element using *Pointer in an expression, including assigning to *Pointer to assign values to that element. You may also refer to the element as Pointer[0], and you may refer to other elements in the same row as Pointer[y], where y is such that 0 ≤ y+c < Columns, i.e., Pointer[y] remains in the same row of the array.
You may also use Pointer[y] to refer to elements of the array in other rows as long as none of the language lawyers see you doing it. (In other words, this behavior is technically not defined by the C standard, but many compilers allow it.) E.g., after Pointer = &Array[r][c];, Pointer[2*Columns+3] will refer to the element Array[r+2][c+3].
To make a pointer you can use to access elements of the array using two dimensions, define int (*Pointer)[Columns] = &Array[r];.
Then Pointer[x][y] will refer to element Array[r+x][y]. In particularly, after int (*Pointer)[Columns] = &Array[0]; or int (*Pointer)[Columns] = Array;, Pointer[x][y] and Array[x][y] will refer to the same element.
You can access any given element with this syntax: array[x][y].
By the same token, you can assign your pointer to any element with this syntax: p = &array[x][y].
In C, you can often treat arrays and pointers as "equivalent". Here is a good explanation:
https://eli.thegreenplace.net/2009/10/21/are-pointers-and-arrays-equivalent-in-c
However, you cannot treat a simple pointer as a 2-d array. Here's a code example:
/*
* Sample output:
*
* array=0x7ffc463d0860
* 1 2 3
* 4 5 6
* 7 8 9
* p=0x7ffc463d0860
* 0x7ffc463d0864:1 0x7ffc463d0868:2 0x7ffc463d086c:3
* 0x7ffc463d0870:4 0x7ffc463d0874:5 0x7ffc463d0878:6
* 0x7ffc463d087c:7 0x7ffc463d0880:8 0x7ffc463d0884:9
*/
#include <stdio.h>
int main()
{
int i, j, *p;
int array[3][3] = {
{1,2,3},
{4,5,6},
{7,8,9}
};
// Dereference 2-D array using indexes
printf("array=%p\n", array);
for (i=0; i < 3; i++) {
for (j=0; j < 3; j++)
printf ("%d ", array[i][j]);
printf ("\n");
}
// Dereference 2-D array using pointer
p = &array[0][0];
printf("p=%p\n", p);
for (i=0; i < 3; i++) {
for (j=0; j < 3; j++)
printf ("%p:%d ", p, *p++);
printf ("\n");
}
/* Compile error: subscripted value p[0][0] is neither array nor pointer nor vector
p = &array[0][0];
printf("p=%p, p[0]=%p, p[0][0]=%p\n", p, &p[0], &p[0][0]);
*/
return 0;
}
Cast the 2D-array into 1D-array to pass it to a pointer,
And then, You are ready to access array with pointer. You can use this method to pass 2D-array to a function too.
#include <stdio.h>
int main()
{
int arr[2][2];
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
arr[i][j] = (2 * i) + j;
}
}
int *Pointer = (int *)arr; // Type conversion
/*
&arr[0][0] = Pointer + 0
&arr[0][1] = Pointer + 1
&arr[1][2] = Pointer + 2
&arr[2][2] = Pointer + 3
Dereference Pointer to access variable behind the address
*(Pointer + 0) = arr[0][0]
*(Pointer + 1) = arr[0][1]
*(Pointer + 2) = arr[1][2]
*(Pointer + 3) = arr[2][2]
*/
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
printf("%d ", *(Pointer + (2 * i) + j)); // Accessing array with pointer
}
printf("\n");
}
return 0;
}
Using the function wv_matalloc from https://www.ratrabbit.nl/ratrabbit/content/sw/matalloc/introduction , you can write the following code:
#include <stdio.h>
#include "wv_matalloc.h"
int main()
{
double **matrix;
int m = 3;
int n = 4;
// allocate m*n matrix:
matrix = wv_matalloc(sizeof(double),0,2,m,n);
// example of usage:
int i,j;
for (i=0; i<m; i++)
for (j=0; j<n; j++)
matrix[i][j] = i*j;
printf("2 3: %f\n",matrix[2][3]);
}
Compile with:
cc -o main main.c wv_matalloc.c
1.
You never assigned a value to Pointer in your example. Thus, attempting to access array by Pointer invokes undefined behavior.
You need to assign Pointer by the address of the first element of array if the pointer shall be a reference:
Pointer = *array;
2.
You can't use 2D notation (p[1][1]) for a pointer to int. This is a C syntax violation.
3.
Since rows of static 2D arrays are allocated subsequent in memory, you also can count the number of array elements until the specific element of desire. You need to subtract the count by 1 since indexing start at 0, not 1.
How does it work?
Each row of array contains 2 elements. a[1][1] (the first element of the second row) is directly stored after the first two.
Note: This is not the best approach. But worth a note beside all other answers as possible solution.
#include <stdio.h>
int main (void)
{
int *Pointer;
static int array[2][2];
Pointer = *array;
Pointer[2] = 6;
printf("array[1][1] (by pointer) = %d\n", Pointer[3]);
printf("array[1][1] (by array istelf) = %d\n", array[1][1]);
}
Output:
array[2][2] (by pointer) = 6
array[2][2] (by array istelf) = 6
Side Notes:
To address the first element of the second row by array[1][2] invokes undefined behavior. You should not use this way.
"but when compiling, I get a segmentation fault error."
Segmentation fault error do not occur at compile time. They occur at run time. It just gives you the impression because high probably your implementation immediately executes the program after compilation.

Can I declare a pointer to a 2d array before I know the dimensions?

I know that one way to declare a pointer to a 2d array is like this:
int(*p)[100];
Then after assigning it to something, I can use elements like this:
p[1][6] = 18;
But let's say I don't yet know the dimensions of the array and I intend to malloc them when I find out.
One solution is that I declare a pointer to just an int, then use pointer arithmetic to navigate the array. I usually do this, but this time I'd like to use the square bracket notation for convenience.
So how do I declare this pointer when I don't yet know the dimensions and I intend to use square bracket notation?
So how do I declare this pointer when I don't yet know the dimensions and I intend to use square bracket notation?
You can use a pointer to a pointer.
int** p = NULL;
and later....
p = malloc(N*sizeof(int*));
for (int i = 0; i < N; ++i )
{
p[i] = malloc(M*sizeof(int));
}
and make sure to deallocate in multiple steps.
for (int i = 0; i < N; ++i )
{
free(p[i]);
}
free(p);
Another way.
// Allocate memory for the pointers.
p = malloc(N*sizeof(int*));
// Allocate memory for the ints.
p[0] = malloc(M*N*sizeof(int));
// Assign the values to the elements of p.
for (int i = 1; i < N; ++i )
{
p[i] = p[i-1] + M;
}
and deallocate in only two steps.
free(p[0]);
free(p);
Simply use a pointer to a variable length array.
Your sizes, y rows with x elements:
size_t x = 123;
size_t y = 30;
Allocate in with one call, sizeof(*p) is identical to sizeof(int) * 123:
int (*p)[x] = malloc( sizeof(*p) * y );
And iterate the 2d array:
for( size_t i = 0 ; i < y ; i++ )
for( size_t j = 0 ; j < x ; j++ )
p[i][j] = 0;
int(*p)[100];
This is not you want . This is pointer to array of int.
What you want is pointer to pointer to int.
int **p;
p=malloc(sizeof(int *)*r); // allocate memory for r number of int *
for(int i=0;i<r;i++)
p[i]=malloc(sizeof(int)*c); // allocate memory to each pointer
free in similar manner.
To index an array of arrays rather than an array of pointers, you can use this trick:
#include <stdlib.h>
#include <stdio.h>
void f( const size_t m, const size_t n, const char s[m][n] )
{
printf( "%s, %s!\n", s[0], s[1] );
return;
}
int main(void) {
static const char hello[][6] = { "hello", "world" };
f( sizeof(hello)/sizeof(hello[0]), sizeof(hello[0]), hello );
return EXIT_SUCCESS;
}
Your question is tagged C and not C++, but C++ does have references to arrays: int (&foo)[m][n] = bar;

Having trouble returning C returning array

I declare hws globally and try to return it in this method but I get a pointer error. I was wondering if anyone knew why that is and could suggest a solution? Randomize just get a random number.
extern int hws[100][20];
int randomize()
{
int value;
int tru_fals = 0;
value = -1;
while ( tru_fals != 1 )
{
value = rand();
if ( 0 < value )
{
if( 101 > value )
{
tru_fals = 1;
}
}
}
return value;
}
int *populate()
{
int i, j;
i = 0;
j = 0;
while( i < 20 )
{
while ( j < 100)
{
int temp = randomize();
hws[i][j] = temp;
j++;
}
i++;
}
return hws;
}
there is a bug: the array is declared as 100x20 but then you iterate through it like it is 20x100.
You define extern int hws[100][20];.
This doesn't create any array. It just says that somewhere in the program, there should be one.
To make it work, some other source file must really define the array - int hws[100][20]; (without extern). Then, if you compile both and link together, it should work.
If you only want one source file, it's much easier - just remove extern.
But: Just noticed Serge's answer, which is actually the real cause of the problem.
Except when it is the operand of the sizeof, _Alignof, or unary & operator, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and its value will be the address of the first element in the array (6.3.2.1/3).
In the line return hws; in populate, the type of the expression hws is "100-element array of 20-element array of int"; by the rule above, it will be converted to type "pointer to 20-element array of int", or int (*)[20]. Thus, the correct declaration for populate would need to be
int (*populate())[20]
{
...
return hws;
}
which reads as
populate -- populate
populate() -- is a function
*populate() -- returning a pointer
(*populate())[20] -- to a 20-element array
int (*populate())[20] -- of int.
and the type of whatever you return the result to would need to be int (*)[20] as well.
Having said that...
Using global variables this way is highly discouraged for a number of reasons. It would be better to pass the array in to populate as a parameter, like so:
void populate(int (*arr)[20], size_t rows)
{
size_t i, j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < 20; j++)
{
arr[i][j] = randomize();
}
}
}
You would call this as simply
populate(hws, sizeof hws / sizeof hws[0]);
If you're using a compiler that supports variable length arrays (either a C99 compiler or a C2011 compiler that does not define __STDC_NO_VLA__ or defines it to 0), you could define the function as
void populate(size_t cols, size_t rows, int (*arr)[cols]) // cols must be declared
{ // before it can be used
size_t i, j; // to declare arr
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
arr[i][j] = randomize();
}
}
}
and call it as
size_t rows = sizeof hws[0] / sizeof hws[0][0]; // dividing the size of the array
size_t cols = sizeof hws / sizeof hws[0]; // by the size of the first element
populate(cols, rows, hws); // gives the number of elements
so you're not hardcoding the 20 anywhere.
If you aren't using a compiler that supports variable length arrays, and you don't want to hardcode the number of rows in the function prototype, you can do something like this:
void populate(int *arr, size_t rows, size_t cols)
{
size_t i, j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
arr[i * rows + j] = randomize();
}
}
}
and call it as
// rows and cols calculated as above
populate(&hws[0][0], rows, cols);
In this case, instead of passing a pointer to the array, we pass a pointer to the first element (the address value is the same, but the type is int * instead of int (*)[20]. So the populate function treats it like a 1D array, and computes the offset with i * rows + j. Note that this trick will only work for 2D arrays that have been allocated contiguously.
This also means that populate can work with arrays of any size, not just Nx20.
hws is a matrix, it means that its and int **
You are returning and int * so you are having a pointer type mismatch.
First, it doesn't need to be returned since it's global. Second, it is a pointer to a pointer to an int. It's an array of an array.

Resources