How to access pointer to 2-d array in c struct? - c

I am having trouble with following struct for using it as Matrix
struct{
int col;
int row;
int (*p)[col];//In this line compiler is giving error, saying col undeclared here.
}Matrix;
I searched on internet and I found a solution which says to write
int (*p)[col]
as
int (*p)[]
Compiler passes it, no issues.
But when I want to increment p using Matrix variable say m
++(m.p);
compiler gives another errors (two) in the same line of code, which says
increment of pointer to unknown structure.
arithmetic on pointer to an incomplete type.
Please tell me why the compiler is giving the above mentioned errors?
What I finally want is to have a pointer in the structure which points to 2-d dynamic array of integers.
So,How to do it???

If you truly want a pointer to an arbitrary 2d array that changes, you will have to use a void pointer. (I don't recommend it, it's unsafe, design should probably be changed.)
struct
{
int col;
int row;
void* p;
}
Before you access the memory, use a local variable-length array pointer. Take the void pointer in the struct, and assign to it the
local vla pointer, using the information from the struct:
struct Matrix x = ...;
int (*n)[x.col] = x.p;
And then use it:
n[0][0] = ...
If you want to increment the void pointer in the struct, simply increment the local pointer, and assign it back to the void pointer:
n++;
x.p = n;
No casting is necessary, just a declaration of a local pointer. If that is a nuisance, operations on void pointer in the struct can be abstracted using inline functions. This should also be done for the sake of safety.

The field declaration int (*p)[col]; is not valid because the compiler don't know the value of col. What you need is a pointer to a pointer, int **p, where p[i] designates the i:th row in the two-dimensional array.
Here is a complete example with a convenient memory allocation macro:
#include <stdlib.h>
#define NEW_ARRAY(ptr, n) (ptr) = calloc((n) * sizeof (ptr)[0], sizeof (ptr)[0])
struct Matrix {
int rows;
int cols;
int **items;
};
void InitializeMatrix(int rows, int cols, struct Matrix *A)
{
int i;
A->rows = rows;
A->cols = cols;
NEW_ARRAY(A->items, rows);
for (i = 0; i < rows; i++) {
NEW_ARRAY(A->items[i], cols);
}
}
int main(void)
{
struct Matrix A;
InitializeMatrix(10, 20, &A);
return 0;
}

When an array is declared then the memory needs to be allocated separately.
struct Matrix{
int col;
int row;
int *Matrix[100];
};
More flexibile:
struct Matrix{
int col;
int row;
int **Matrix;
}
struct Matrix A;
A.col =10;
A.row = 10;
/* Allocate memory here for the Matrix */
You can declare and allocate memory for a 2D arrays using different methods.
/* Access the Matrix */
A.Matrix[i][j] = value;

Related

How to get a 2 dimensional array as output of a user defined function?

I am trying to write a user defined function that takes some matrices and variables as inputs and gives a matrix as output. So something like this:
cofactor(int A[100][100], n, r, c){
int B[100][100]
//B becomes the cofactor matrix of A after some operations//
return B;
}
and in my main function I just want to write :
C=cofactor(D, n, r, c);
to turn C into the cofactor matrix of D.
But for some reason c language does not support taking a whole 2D array as output of a function. How can I work around this?
I don't want to keep all the junk in the main function. I want to write a separate function that gives me the matrix as output, and simply call that function in my main function.
Currently in your code B will go out of scope and will be destroyed when control exits cofactor.
Thus use pointer to pointer as below.
int **cofactor(int A[100][100], int n, int r, int c){
int **B = malloc(sizeof(int *)*r);
for (int i =0;i<r;i++)
B[i] = malloc(sizeof(int)*c);
//B becomes the cofactor matrix of A after some operations//
return B;
}
And from main.
int **C=cofactor(D, n, r, c);
Note:: NULL checks are not added and allocated memory needs to be freed once done with the processing.
You are correct in that C doesn't allow us to return arrays from functions. This is one area where C is simply plain bad and you'll find yourself choosing between various evils.
The most obvious alternatives are to return an array pointer, or a void pointer.
void pointers should be avoided since they have non-existent type safety.
// bad code
void* cofactor (int A[100][100], int n, size_t r, size_t c)
The array pointer option is rather ugly-looking, hard to read and enforces fixed-size dimensions:
// bad code
int ( *cofactor (int A[100][100], int n, size_t r, size_t c) )[100][100];
Alternatively, also ugly and bad practice, is to hide the array type behind a typedef:
// bad code
typedef int arr_t [100][100];
arr_t* cofactor(int A[100][100], int n, size_t r, size_t c)
The array pointer versions also have the limit that you can't use variable dimensions. But r and c here seem to be rows and columns, so you probably do want the array to have variable size.
This is where some start to use int** out of confusion. But int** cannot be used to point at a 2D array, nor to the first element of a 2D array. It can be used to point at the first element of a 1D array of int* pointers, and then emulate something that looks like an array, but doesn't behave like one. That's not what you want here either, because it is both slow and dangerous. See Correctly allocating multi-dimensional arrays.
Sigh. So what to use!
If you drop the requirement of "function return ing array" (with emphasis on using return), it turns easier and more flexible. Parameter passing to/from functions in C is most often done through the parameters, and most sound APIs reserve the return value for an error type describing the outcome of the function.
The big advantage here is that when passing an array as parameter, we can use variable dimensions:
void func (size_t r, size_t c, int A[r][c])
Suddenly you can have a function accepting any array size, and somewhat type safe as long as r and c have correct values.
The cleanest is to leave allocation to the caller. Then you get
void func (size_t r, size_t c, int A[r][c], int B[r][c])
Out of all options discussed, this is the only pretty one. But it won't work if the function must do the allocation. Then we must return an array through the parameter. And to that with this syntax, turns a bit ugly too:
void copy (size_t r, size_t c, int (**B)[r][c], int A[r][c])
But if we can live with this strange-looking "pointer to array pointer to an array of int[r][c]", then it solves all problems. It can return an array of variable size from a function to the caller.
A function making a copy of any array and returning it would look like this:
void copy (size_t r, size_t c, int (**B)[r][c], int A[r][c])
{
*B = malloc( sizeof(int[r][c]) );
int (*b)[c] = **B; // pointer to the first row in an array int[r][c]
for(size_t i=0; i<r; i++)
{
for(size_t j=0; j<c; j++)
{
b[i][j] = A[i][j];
}
}
}
Or if you will:
#include <string.h>
void copy (size_t r, size_t c, int (**B)[r][c], int A[r][c])
{
*B = malloc( sizeof(int[r][c]) );
memcpy( *B, A, sizeof(int[r][c]) );
}
Full example:
#include <stdlib.h>
#include <stdio.h>
void copy (size_t r, size_t c, int (**B)[r][c], int A[r][c])
{
*B = malloc( sizeof(int[r][c]) );
int (*b)[c] = **B; // pointer to the first row in an array int[r][c]
for(size_t i=0; i<r; i++)
{
for(size_t j=0; j<c; j++)
{
b[i][j] = A[i][j];
}
}
}
int main (void)
{
int array1[2][3] = { {1,2,3}, {4,5,6} };
int (*array2)[2][3];
copy(2, 3, &array2, array1);
int (*arr)[3] = *array2;
for(size_t i=0; i<2; i++)
{
for(size_t j=0; j<3; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
free(array2);
}

Why is my pointer giving back value at address directly?

Here is my code:
typedef struct {
int** matrix;
int rows;
int cols;
}intMat;
intMat create_intMat(int rows,int cols,int matrix[rows][cols]){
intMat A;
A.rows = rows;
A.cols = cols;
int** mat;
mat = malloc(A.rows*sizeof(int*)); // Pointer for matrix rows
for(int i=0;i<A.rows;i++) mat[i] = malloc(A.cols*sizeof(int)); // Pointer of each matrix row to a matrix column
for (int i=0;i<A.rows;i++){
for (int j=0;j<A.cols;j++){
mat[i][j]=matrix[i][j];
}
}
A.matrix = mat;
return A;
}
int main() {
int mat[2][2] = {{1,2},{3,4}};
intMat A;
A = create_intMat(2,2,mat);
printf("%d\n",A.matrix[1][1]);
return 0;
}
I'm a beginner to pointers and got the pointer part of the code from another forum. I don't get it, though. int** mat is a pointer to a pointer to an int, so if I call it as is then it should give me back gibberish address, not the int being pointed to. However, the printf statement returns 4, which is the value of the int being pointed to! How come this is happening?
A.matrix is a pointer to a 2 pointers, which each point to 2 ints.
A.matrix[1] gets the second of those pointers - a pointer to 2 ints.
A.matrix[1][1] gets the second of those ints.
When you use:
int i;
int* p = &i;
or
int* p = malloc(sizeof(int));
p points to a single integer.
When you use:
int array[10];
int *p = array;
or
int *p = malloc(sizeof(int)*10);
p points to an array of 10 integers.
Similarly, a variable declared with:
int** mat;
can point to one int* or an array of int*s.
In your case, mat points to an array of 2 int*, each of which points to an array of 2 ints.
That makes use of mat[1][1] perfectly valid code.

What does this symbol ** mean in the C language

Hi I'm new to the C language, can someone explains what ** symbol mean.
typedef struct _TREENODE {
struct _TREENODE *Left, *Right;
TCHAR key[KEY_SIZE];
LPTSTR pData;
} TREENODE, *LPTNODE, **LPPTNODE;
If x is a pointer, *x dereferences it. **x is the same as *(*x), so **x dereferences a pointer to a pointer. (eg, it is the thing that is pointed to by the thing that x opints to).
** is a pointer to pointer, it is also used for dereferencing a pointer variable.
eg: int a=10,*b,**c;
b=&a;
c=&b;
printf("the a value is:%d\n",a);
printf("the b value is:%d\n",*b);
printf("the c value is:%d\n",**c);
just execute this code you will get the idea about pointer to pointer.
In you want to change a variable, you pass it by pointer (to the variable).
And if you want to change a pointer, you also pass it by pointer (to the pointer) which is a double pointer.
There are two things to know about * in C:
It's an operation. Doing *x on a pointer dereferences that pointer. Doing **x on a pointer can dereference a pointer to a pointer, and so on.
It's a type. Declaring a type of int *x means that it's a pointer to an int type. Declaring int **x means that it's a pointer to a pointer to an int type.
Example:
int main() {
int foo = 4;
int *bar = &foo; // declaring a pointer to int type *bar
int **baz = &bar; // declaring a pointer to a pointer to int type **baz
printf("foo: %d, *bar: %d, **baz: %d\n", foo, *bar, **baz); // derefencing the pointer *bar and **baz
return 0;
}
In a declaration, ** means pointer to a pointer. When evaluating an expression, ** dereferences a pointer to a pointer.
int** p; // Declares p to be a pointer to a pointer.
And...
**p = 10; // Dereferences p and assigns 10 to a memory location.
One common use of pointers to pointers is to represent dynamic 2D arrays. For example, if you want to create a matrix of M rows and N columns, you could do:
int** matrix = malloc(M*sizeof(*matrix));
int i = 0, j = 0;
for ( i = 0; i < M; ++i )
matrix[i] = malloc(N*sizeof(*matrix[0]));
Usage of the double pointer:
for ( i = 0; i < M; ++i )
for ( j = 0; j < N; ++j )
matrix[i][j] = 0; // Assigns a value to the element
// at the i-th row and j-th column.
If you want to use string pointer dereferencing, you would use:
for ( i = 0; i < M; ++i )
for ( j = 0; j < N; ++j )
*(*(matrix+i)+j) = 0;
Memory allocated for the matrix has to be freed in two passes also.
for ( i = 0; i < M; ++i )
free(matrix[i]);
free(matrix);
** means a pointer to a pointer.
Most of the time I like to think of it as "pointer(s)" to "a memory area". Which in fact may be a little redundant.
For example, suppose you have to dynamically store several words on memory, how would you do that? There are several ways to do this, but I'll provide an example that illustrate the use of **.
Now, suppose you want to store three words: hi, hello and goodbye
hi, hello and goodbye are strings, they consume, 2, 5 and 7 bytes on memory respectively. Well, in fact it's 3, 6 and 8 bytes because of the \0, but lets not get into many details.
But one thing is clear, we need three memory areas to hold these strings and also three pointers to reference these memory areas later.
Note that one can just declare three pointers that points to these memory areas, but, would you be willing to declare one thousand pointers to hold one thousand words? This is where ** kicks in.
Example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUMBER_OF_WORDS 3
int
main(int argc, char **argv)
{
int i;
char **words;
/* pointers */
words = malloc(sizeof(char*)*NUMBER_OF_WORDS);
/* memory areas*/
words[0] = strdup("Hi");
words[1] = strdup("Hello");
words[2] = strdup("Goodbye");
for(i=0; i < NUMBER_OF_WORDS; i++)
printf("%d) %s\n", i, words[i]);
for(i=0; i < NUMBER_OF_WORDS; i++)
free(words[i]); /* memory area */
free(words); /* pointers */
return 0;
}

Variable array size in c

I'm trying to declare arrays with a variable size, given by user input.
So far I have something like this:
typedef struct _object{
int rowsAmount;
int columsAmount;
int* rows;
int* colums;
} object;
object* newObject(int ra, int ca){
object* o = malloc(sizeof(object));
o->rowsAmount = ra;
o->columsAmount = ca;
o->rows = [ra];
o->colums = [ca];
return o;
}
int main(){
newObject(3,4);
}
I expected this wouldn't work, but I want something like this, and I don't know how to do it.
It looks like you're basically implementing a dynamic Matrix object here. You want something like:
typedef struct _object{
int rowsAmount;
int columsAmount;
int* matrix;
int** rows;
} object;
object* newObject(int ra, int ca){
object* o = malloc(sizeof(object));
o->rowsAmount = ra;
o->columsAmount = ca;
o->matrix = malloc(ra * ca * sizeof(int));
o->rows = malloc(ra * sizeof(int*));
for (size_t i = 0; i != ra; ++i) o->rows[i] = o->matrix + (i * ca);
return o;
}
You should also create a destructor function destroyObject, which similarly frees all the memory allocated for o and o->matrix.
Edit:
However, your comment that:
"I'm just trying to learn c, this is only about the setting the size.
I just happened to try it with 2 arrays"
...makes this question somewhat confusing, because it indicates you are not, in fact, trying to create a matrix (2D array) despite your use of "row"/"column" terminology here, but that you simply want to understand how to dynamically allocate arrays in C.
If that's the case, an array in C is dynamically allocated using a pointer variable and malloc:
size_t array_size = 10; /* can be provided by user input */
int* array = malloc(sizeof(int) * array_size);
And then later, the dynamically-allocated array must be freed once you are finished working with it:
free(array);
To dynamically allocate a 2d array of data in C:
Allocate the memory for the entire data. That memory is pointed to by arrayData.
Allocate an 1D Array of pointers one for each row
Point those pointers to the memory address corresponding each row
Code:
int *arrayData = malloc(sizeof(int) * rows * columns);
int **array = malloc(sizeof(int*) * rows);
for(int i=0; i < rows;++i){
array[i] = arrayData + i * columns;
}
You can now access the memory as array[row][col].
You can create a array with size input from user with out a structure.
int *array1;
int size;
// get input from user
array1 = malloc(sizeof(int)*size);
// do your stuff
free(array1);
if you want a 2D array,
int **array2;
int row, col;
int i;
array2 = malloc(sizeof(int*)*row);
for(i=0;i<row;++i)
array2[i] = malloc(sizeof(int)*col);
//use the array
for(i=0;i<row;++i)
free(array2[i]);
free(array2);
if you really need a structure array, then allocate memory for it in your newObject() function
typedef struct _object{
int rowsAmount;
int columsAmount;
int** array;
//int* colums;
} object;
object* newObject(int ra, int ca){
int i;
object* o = malloc(sizeof(object));
o->rowsAmount = ra;
o->columsAmount = ca;
o->array = malloc(sizeof(int*)*ra);
for(i=0;i<ra;i++)
o-<array[i]=malloc(sizeof(int)*ca);
return o;
}
int main(){
newObject(3,4);
}
I think that quite often people use dynamic memory allocation when scoped variables can be used instead. For example, array sized from user's input can be allocated on stack without using malloc/free:
int array_size;
scanf("%d", &array_size);
if (array_size > 0) {
/* Allocate array on stack */
float array[array_size];
/* ... do smth with array ... */
}
/* Out of scope, no need to free array */
Of course if your data block is huge, heap memory is a must, but for small allocations scopes are just fine.
Easiest way is to use boost::multi_array
Not only will you get any number of dimensions, it's also stored very efficiently as a single contiguous block of memory rather than n dimensional array.
CPU's are designed to traverse arrays quickly, and you could potentially utilise caching/prefetch/pipelining features of the compiler using this.
Eg
// 2 dimensions
int xDim;
int yDim;
cin >> xDim; // From user..
cin >> yDim;
// Initialise array
boost::multi_array<int,2> my2dgrid(boost::extents[xDim][yDim]);
// Iterate through rows/colums
for(int j = 0 ; j < yDim-1; j++) { // Row traversal
for(int i = 0 ; i < xDim-1; i++) { // Column traversal
int value = grid[j][i]; // Get a value
grid[j][i] = 123; // set a value
// Do something...
}
#include <stdio.h>
#include <stdlib.h>
typedef struct _object{
int rowsAmount;
int columsAmount;
int **rows;
// int* colums;
} object;
object* newObject(int ra, int ca){
int r;
object* o = malloc(sizeof(object));
o->rowsAmount = ra;
o->columsAmount = ca;
o->rows = (int **)malloc(ra*sizeof(int *));
for(r=0;r<ra;++r)
o->rows[r] = (int*)malloc(ca*sizeof(int));
return o;
}
int main(){
object *obj= newObject(3,4);
obj->rows[2][3]=5;
return 0;
}

Random matrix struct creation

I'm trying to make a struct that generates a random matrix and am getting "error: expected â=â, â,â, â;â, âasmâ or â_attribute_â before âmatrixâ" when compiling. How can I get this to work effectively and efficiently?
I guess expected errors usually are caused by typos but I don't see any.
I'm very new to C so pointers and malloc are quite foreign to me. I really appreciate your help.
/* It's called RandomMatrixMaker.c */
#include <stdio.h>
#include <stdlib.h>
typdef struct {
char* name;
int MID;
int MRows;
int MCols;
long[][]* MSpace;
} matrix;
matrix makeRIDMatrix(char* name, int MID, int MRows, int MCols) {
matrix m;
static int i, j, r;
m.name = name;
m.MID = MID;
m.MRows = MRows;
m.MCols = MCols;
for (i=0; i<m.MRows; i++) {
for (j=0; i<m.MCols; j++) {
r = random(101);
*(m.MSpace[i][j]) = r;
}
}
return m;
}
int main(void) {
makeRIDMatrix("test", 1, 10, 10);
return 0;
}
There is indeed a typo. You misspelled typedef:
typdef struct {
should be:
typedef struct {
EDIT:
Also, there's no reason to use static here:
static int i, j, r;
You can just get rid of the static modifier.
int i, j, r;
As another poster mentioned, there's a typo, but even with that corrected, it wouldn't compile, due to the definition of matrix.MSpace.
Let's begin in makeRIDMatrix(). You've declared an automatic (stack) variable of type "matrix". At the end of the function, you return that object. Whilst this is permissible, it's not advisable. If the struct is large, you will be copying a lot of data unnecessarily. Better to pass a pointer to a matrix into makeRIDMatrix(), and have makeRIDMatrix() fill in the contents.
The test in the inner loop is against i, but should be against j.
Next, let's look at the definition of "matrix". The definition of "MSpace" is a mess, and wouldn't even compile. Even if it did, because you haven't defined the length of a row, the compiler would not be able to calcuate the offset to any given item in the array. You want a two-dimensional array without giving the row length, but you can't do that in C. You can in other languages, but not C.
There's a lot more I could point out, but I'd be missing the real point. The real point is this:
C Is Not Java.
(It's also not one of the interpreted languages such as JavaScript, PHP, Python, Ruby and so on.)
You don't get dynamically-expanding arrays; you don't get automatic allocation of memory; you don't get garbage collection of unreferenced memory.
What you need is something more like this:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct {
char* name;
int MID;
unsigned int MRows;
unsigned int MCols;
long *MSpace;
} matrix;
void makeRIDMatrix(matrix *pmx, char* name, int MID,
unsigned int MRows, unsigned int MCols) {
int i, j;
long *MSpace = malloc(sizeof(*MSpace)*MRows*MCols);
if (MSpace == NULL) {
return;
}
pmx->name = name;
pmx->MID = MID;
pmx->MRows = MRows;
pmx->MCols = MCols;
pmx->MSpace = MSpace;
srandom((unsigned int)time(NULL));
for (i=0; i<MRows; i++) {
for (j=0; i<MCols; j++) {
long int r = random() % 101L;
*(MSpace++) = r;
}
}
}
inline long * item_addr(const matrix *pmx,
unsigned int row, unsigned int col) {
if (pmx == NULL || pmx->MSpace == NULL
|| row >= pmx->MRows || col >= pmx->MCols) {
return NULL;
}
return &(pmx->MSpace[row * pmx->MCols + col]);
}
long get_item(const matrix *pmx, unsigned int row, unsigned int col) {
long *addr = item_addr(pmx, row, col);
return addr == NULL ? 0L : *addr;
}
void set_item(matrix *pmx,
unsigned int row, unsigned int col,
long val) {
long *addr = item_addr(pmx, row, col);
if (addr != NULL) {
*addr = val;
}
}
int main(void) {
matrix m;
makeRIDMatrix(&m, "test", 1, 10, 10);
return 0;
}
Note a few things here. Firstly, for efficiency, I fill the array as if it were one-dimensional. All subsequent get/set of array items should be done through the getter/setter functions, for safety.
Secondly, a hidden nasty: makeRIDMatrix() has used malloc() to allocate the memory - but it's going to be job of the calling function (or its successors) explciitly to free() the allocated pointer when it's finished with.
Thirdly, I've changed the rows/cols variables to unsigned int - there's little sense in definining an array with negative indices!
Fourthly: little error checking. For example, makeRIDMatrix() neither knows nor cares whether the parameter values are sensible (e.g. the matrix pointer isn't checked for NULLness). That's an exercise for the student.
Fifthly, I've fixed your random number usage - after a fashion. Another exercise for the student: why is the way I did it not good practice?
However - all of this is moot. You need to get yourself a good C textbook, or a good online course, and work through the examples. The code you've given here shows that you're punching above your weight at the moment, and you need to develop some more C muscles before going into that ring!
In relation to your question about "variable sized arrays", you could have something like:
/* can stick this into your struct, this is just an example */
size_t rows, cols;
long **matrix;
/* set the values of rows, cols */
/* create the "array" of rows (array of pointers to longs) */
matrix = (long**)malloc(rows * sizeof(long*));
/* create the array of columns (array of longs at each row) */
for (i = 0; i < rows; i++)
matrix[i] = (long*)malloc(cols * sizeof(long));
/* ... */
/* free the memory at the end */
for (i = 0; i < rows; i++)
free(matrix[i]);
free(matrix);
Then you can just access the dynamically allocated matrix similar to any other array of arrays.
ie. to set element at the first row (row 0) and fourth column (column 3) to 5:
matrix[0][3] = 5;

Resources