I haven't used pure C in a few years now, but I can't seem to make this really basic use case work. Here is the simple use-case in simple C, the actual situation is wrapped in the HDF library, but I need to start with this, first.
#include <stdio.h>
void print_data(float **data, int I, int J)
{
for(int i=0;i<I;i++)
{
for(int j=0;j<J;j++)
printf("%02.2f\t", data[i][j]);
printf("\n");
}
}
void initialize_data(float **data, int I, int J)
{
for(int i=0;i<I;i++)
for(int j=0;j<J;j++)
data[i][j] = i * 6 + j + 1;
}
int main(int argc, char *argv[])
{
float data[4][6];
int I=4;
int J=6;
initialize_data((float **)data, 4,6);
print_data((float **)data, 4, 6);
return 0;
}
The above program will cause a failure and raise a EXC_BAD_ACCESS signal. GDB outputs:
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00007fff5fc0131a
0x0000000100000de6 in initialize_data (data=0x7fff5fbff348, I=4, J=6) at simple.c:16
16 data[i][j] = i * 6 + j + 1;
I know this is really stupid simple, but I'm at my wits' ends trying to figure out this simple thing. Could someone point me in the right direction for this?
void print_data(float **data, int I, int J)
expects an array of pointers to (the first element of arrays of) float.
But when you pass
float data[4][6];
you pass a pointer to float[6].
So in print_data, an access to
data[i]
reads sizeof(float*) bytes at an offset of i * sizeof(float*) bytes after what address data holds, and interprets these bytes as a float* that it then dereferences (after adding a suitable offset) in data[i][j].
So when you pass your 2D array, some float values are interpreted as pointers and then followed. That often leads to a segmentation fault.
You can either declare
void print_data(float (*data)[6], int I, int J)
and pass your 2D array, or you need to pass an array of pointers,
float *rows[4];
for(i = 0; i < 4; ++i) {
rows[i] = &data[i][0];
}
and pass rows. Or, the third possibility is to pass and expect a flat array
void initialize_data(float* data, int I, int J) {
for(i = 0; i < I; ++i) {
for(j = 0; j < J; ++j) {
data[i*J + j] = whatever;
}
}
}
and pass &data[0][0] from main.
A bi-dimensionnal array is not evaluated as a pointer to pointer, so you need to use an array of a pointer to array in your prototype:
void print_data(float data[4][6]);
void print_data(float (*data)[6]);
Related
I want to pass a 2D array already filled with chars to a different method to do something with it.
Background: I am trying to implement GameOfLife. And I have already successfully implement the gameboard with a random amount of living cells. But now I want to pass the board(Array) to a different method to continue working with it. How to do so?
//wow das wird hurenshon
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
void spielStarten(int x, int amountOfLiving){
char feld[x][x];
for(int i = 0; i < x; i++){
for(int j = 0; j < x; j++){
feld[i][j] = 'o';
}
}
for(int i = 0; i < amountOfLiving; i++){
int a = (rand()%x);
int b = (rand()%x);
feld[a][b] = 'x';
}
printf("Gameboard: \n");
for(int i = 0; i < x; i++){
for(int j = 0; j < x; j++){
printf("%c ", feld[i][j]);
}
printf("\n");
}
spielRun(feld);
}
void spielRun(char feld[][]){
int neighbCount;
char feldNew[][] = feld[][];
for(int i = 0; i < x; i++) {
for(int j = 0; j < x; j++) {
checkForNeighbours(feld[x][y]);
// in progress
}
}
}
int main(int argc, char* argv[]){
srand(time(NULL));
int x = 16;
if(argc < 2 || argc > 3){
printf("2. Argument eine Zahl fuer Feldgroesse eingeben\n");
printf("1. Argument eine Zahl 0-10 fuer ungefähre prozentuale Belegung mit lebenden
Zellen eingeben \n");
return 0;
}
if(argv[2] != NULL){
x = atoi(argv[2]);
}
int i;
i = atoi(argv[1]);
i = (x^2)*(0,1*i);
spielStarten (x,i);
return 0;
}
In the last line of the Method "Spiel starten" i want to give the array to the next Method "spielRun".
Edit: thanks to an other user I found this struture:
void printarray( char (*array)[50], int SIZE )
But it doesn't work for me since I can´t hardcode the number, because the arraysize depends on a user input.
thanks!
The difficulty here is that the size of your array is not known statically (once upon a time, your code would even not compile for the same reason).
That, combined with the fact that 2D-arrays are not arrays of 1D arrays (contrarily to what happen when you malloc a int ** and then every int * in it), and so it doesn't make sense not to specify the size when passing it to a function.
When using arrays of arrays (technically, pointers to a bunch of pointers to ints), like this
void f(int **a){
printf("%d %d %d\n", a[0][0], a[1][0], a[0][1]);
}
int main(){
int **t=malloc(10*sizeof(int *));
for(int i=0; i<10; i++) t[i]=malloc(20*sizeof(int));
f(t);
}
That code is useless, it prints only unitialized values. But point is, f understands what values it is supposed to print. Pointers arithmetics tells it what a[1] is, and then what a[1][0] is.
But if this 2D-array is not pointers to pointers, but real arrays, like this
void f(int a[][20]){
printf("%d %d %d\n", a[0][0], a[1][0], a[0][1]);
}
int main(){
int t[10][20];
f(t);
}
Then, it is essential that the called function knows the size (or at least all sizes, but for the first dimension) of the array. Because it is not pointers to pointers. It is an area of 200 ints. The compiler needs to know the shape to deduce that t[5][3] is the 5×20+3=103th int at address t.
So, that is roughly what is (better) explained in the link that was given in comments: you need to specify the size.
Like I did here.
Now, in your case, it is more complicated, because you don't know (statically) the size.
So three methods. You could switch to pointers to pointers. You could cast your array into a char * and then do the index computation yourself (x*i+j). Or with modern enough C, you can just pass the size, and then use it, even in parameters, declaration
void f(int x, int a[][x]){
printf("%d %d %d\n", a[0][0], a[1][0], a[0][1]);
}
int main(){
int t[10][20];
f(t);
}
Anyway, from an applicative point of view (or just to avoid segfault) you need to know the size. So you would have had to pass it. So why not pass it as first parameter (Note that the function in which you have this size problem, spielRun, does refers to a x, which it doesn't know. So, passing the size x would have been your next problem anyway)
So, spielRun could look like this (not commenting in other errors it contains)
void spielRun(int x, char feld[][x]){
int neighbCount;
char feldNew[][] = feld[][]; // Other error
for(int i = 0; i < x; i++) {
for(int j = 0; j < x; j++) {
checkForNeighbours(feld[i][j]); // Corrected one here
// in progress
}
}
}
And then calls to this spielRun could be
spielRun(x, feld);
Note that I address only the passing of array of size x here. There are plenty of other errors, and, anyway, it is obviously not a finished code. For example, you can't neither declare a double array char newFeld[][] = oldFeld[][]; nor affect it that way. You need to explicitly copy that yourself, and to specify size (which you can do, if you pass it).
I am also pretty sure that i = (x^2)*(0,1*i); does not remotely what you expect it to do.
#include <stdio.h>
void arraypass(int from, int to, int a[][2]);
int main()
{
setbuf(stdout, NULL);
int t1 = 0, t2 = 0;
int testArray[10][2];
for (t1 = 0; t1 < 10; t1++)
{
testArray[t1][t2] = t1 + 1;
}
t2++;
for (t1 = 0; t1 < 10; t1++)
{
testArray[t1][t2] = t1 + 10;
}
arraypass(1,5,testArray);
return 0;
}
void arraypass(int from, int to, int a[][2])
{
int b;
for (b = from; b <= to; b++)
{
printf("%d ",a[b][0]);
printf("%d\n",a[b][1]);
}
}
Why is it that
int a[][2]
works, but not
int a[][]
for the argument definitions in this?
void arraypass(int from, int to, int a[][2]);
And, is there a way to possibly pass an entire multidimensional array at once, or do I need to perform some kind of loop?
For the compiler, a vector is a hidden pointer to its first item.
For example:
int a[2];
a[0]=0;
a[1]=1;
is the same of:
int a[2];
*(a+0)=0;
*(a+1)=1;
When you pass a multidimensional array (o a simple array) you should use pointers instead of a vector:
void arraypass(int from, int to, int **a);
and then if you want to use it you could do something like this:
void arraypass(int from, int to, int **a){
int i,j;
for(i=from; i<end; i++) {
for(j=0; j<2; j++) {
printf("%d",a[i][j]);
}
}
You have to remember that arrays decays to pointers. That means, when they are (for example) passed as arguments to functions the function receives a pointer.
What int a[][2] does, is the same as int (*a)[2], which means that a is a pointer to an array of two int. That is different from a pointer to an array of any other dimension, which is why you don't have to specify the primary "dimension" (as that to the compiler is the same as a pointer) but you do have to specify the other "dimension(s)".
This is related to this answer in the C FAQ.
Because the function receives a pointer when an array is passed to a function, the compiler needs to know the dimensionality of the array that the pointer will be to (in this case, two), but doesn't care how long the sequence of pointers to two-element arrays is going to be.
I have successfully fscanf a text file and saved in to an array E2N1. I am trying to pass this into a function as a pointer but it is not working. Whenever I try to call E2N1[0][0], it says that E2N is neither an array or a pointer. I've been looking all over for a solution on this.
(Sorry E2N was meant to be E2N1)
I use fscanf as:
int E2N1[noz.rowE2N][Q.N];
FILE* f = fopen("E2N.txt", "r");
for(i=0; i<noz.rowE2N; i++){
for (j=0; j<Q.N; j++){
fscanf(f,"%d",&E2N1[i][j]);
}
fscanf(f,"\n");
}
fclose(f);
and again I can't pass E2N1 into function.
Your help will be greatly appreciated.
The function is:
double *dudtF = stiffness(&U, &massM, &noz, &newV, &E2N1, &I2E, &B2E, &PP, &QQ);
and I write the function header as:
double *stiffness(double *U, double *massM, MESH *meshN, double *V1, int *E2N1, int *I2E, int *B2E, ordApprox *pp, ordApprox *qq)
V1, I2E, B2E are three arrays and I'm trying to do the same with them as I am trying to do with E2N1.
The funny thing about arrays is that they actually act as pointers.
if you have array char a[3] the variable is equivalent to char* p the same way if you have array char b[3][4] the variable b is equivalent to char** q. In other words, you should consider changing the handling in the method to take reference to reference (and possibly once more to reference) to integer.
Try google... here are some results I've got.
http://www.dailyfreecode.com/code/illustrate-2d-array-int-pointers-929.aspx
http://www.cs.cmu.edu/~ab/15-123S09/lectures/Lecture%2006%20-%20%20Pointer%20to%20a%20pointer.pdf
You don't need to pass as &E2N1, just pass as E2N1 no & as array name itself translates to pointer.
double *dudtF = stiffness(&U, &massM, &noz, &newV, E2N1, &I2E, &B2E, &PP, &QQ);
Also, you need to take it as int ** as its 2-dimensional array.
double *stiffness(double *U, double *massM, MESH *meshN, double *V1, int **E2N1, int *I2E, int *B2E, ordApprox *pp, ordApprox *qq)
Here is the example how to transfer matrix from one function to another ...
void foo (int **a_matrix)
{
int value = a_matrix[9][8];
a_matrix[9][8] = 15;
}
void main ()
{
#define ROWS 10
#define COLUMNS 10
int **matrix = 0;
matrix = new int *[ROWS] ;
for( int i = 0 ; i < ROWS ; i++ )
matrix[i] = new int[COLUMNS];
matrix[9][8] = 5;
int z = matrix[9][8] ;
foo (matrix);
z = matrix[9][8] ;
}
You cannot reference a multi-dimensional array passed to a function by point referencing as in the following:
int iVals[10][10];
foo(iVals);
void foo(int** pvals)
{
// accessing the array as follows will cause an access violation
cout << pvals[0][1]; // access violation or unpredictable results
}
You will need to specify the second dimension to the array in the function prototype
for example:
foo(int ivals[][10])
{
cout << ivals[0][1]; // works fine
}
If do not know the dimensions, then I would suggest you follow the principles outlined here:
void foo(int *p, int r, int c)
{
for(int i=0; i<r; i++)
{
for(int j=0; j<c; j++)
{
printf("%d\n", p[i*c+j]);
}
}
}
int c[6][6];
// pointer to the first element
foo(&c[0][0], 6, 6);
// cast
foo((int*)c, 6, 6);
// dereferencing
foo(c[0], 6, 6);
// dereferencing
foo(*c, 6, 6);
I hope this helps.
Alternatively you could use SAFEARRAY - see:
http://limbioliong.wordpress.com/2011/06/22/passing-multi-dimensional-managed-array-to-c-part-2/
I am trying to malloc a char to have rows and columns with one letter in each cell. Something similar to int x[i][j] where I have i*rows and j*columns. Basically I want to make this:
|
1
222
33333
4444444
I tried with this code but it gives me an error: assignment makes an integer from pointer without a cast
A=(char**) malloc (5*sizeof(char*));
for(i=0;i<N+2;i++)`{
A[i]=(char*) malloc(7*sizeof(char));
}
for(i=0;i<3;i++){
for(j=0;j<7;j++){
left=3;
right=3;
if((j>=left)&&(j<=right)){
A[i][j]=i;
}
}
left--;
right++;
}
I would go with different approach:
#define STEPS 5
#define ARRAY_SIZE STEPS*STEPS
The size of the array in your case can be easily calculated by the formula above.
Now, you just need to allocate fixed size of bytes, and fill it. That's it. Even more, the version below will simply out-beat your version in simplicity and performance.
int i, j;
char *array;
array = malloc(ARRAY_SIZE);
for (i = 0; i < STEPS; i++)
for (j = 0; j < (i * 2 + 1); j++)
*(array + i * STEPS + j) = i + 1;
Proof.
This compiles fine for me, as long as I add this around your code snippet; note that "A" was declared as being of type "char **". It won't work if you write, say "char A[][]".
#include <stdlib.h>
int main() {
const int N = 10;
int i, j, left, right;
char **A;
/* your code */
return 0;
}
I want to create a program in which I can pass a matrix to a function using pointers.
I initialized and scanned 2 matrices in the void main() and then I tried to pass them to a void add function. I think I am going wrong in the syntax of declaration and calling of the function. I assigned a pointer to the base address of my matrix. (for eg: int *x=a[0][0], *y=b[0][0]). What is the right declaration? How can I specify the dimensions?
Given a 2D array of
T a[N][M];
a pointer to that array would look like
T (*ap)[M];
so your add function prototype should look like
void add(int (*a)[COLS], int (*b)[COLS]) {...}
and be called as
int main(void)
{
int a[ROWS][COLS];
int b[ROWS][COLS];
...
add(a, b);
However, this code highlights several problems. First is that your add function is relying on information not passed via the parameter list, but via a global variable or symbolic constant; namely, the number of rows (the number of columns is explicitly provided in the type of the parameters). This tightly couples the add function to this specific program, and makes it hard to reuse elsewhere. For your purposes this may not be a problem, but in general you only want your functions to communicate with their callers through the parameter list and return values.
The second problem is that as written, your function will only work for matrices of ROWS rows and COLS columns; if you want to add matrices of different sizes within the same program, this approach will not work. Ideally you want an add function that can deal with matrices of different sizes, meaning you need to pass the sizes in as separate parameters. It also means we must change the type of the pointer that we pass in.
One possible solution is to treat your matrices as simple pointers to int and manually compute the offsets instead of using subscripts:
void add (int *a, int *b, size_t rows, size_t cols)
{
size_t i;
for (i = 0; i < rows; i++)
{
size_t j;
for (j = 0; j < cols; j++)
{
*(a + cols * i + j) += *(b + cols * i + j);
}
}
}
and call it like so:
int main(void)
{
int a[ROWS][COLS] = {...};
int b[ROWS][COLS] = {...};
int c[ROWS2][COLS2] = {...};
int d[ROWS2][COLS2] = {...};
...
add(a[0], b[0], ROWS, COLS);
add(c[0], d[0], ROWS2, COLS2);
...
}
The types of a[0] and b[0] are "COLS-element arrays of int"; in this context, they'll both be implicitly converted to "pointer to int". Similarly, c[0] and d[0] are also implicitly converted to int *. The offsets in the add() function work because 2D arrays are contiguous.
EDIT I just realized I was responding to caf's example, not the OP, and caf edited his response to show something very similar to my example. C'est la guerre. I'll leave my example as is just to show a slightly different approach. I also think the verbiage about passing information between functions and callers is valuable.
Something like this should do the trick.
#define COLS 3
#define ROWS 2
/* Store sum of matrix a and b in a */
void add(int a[][COLS], int b[][COLS])
{
int i, j;
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
a[i][j] += b[i][j];
}
int main()
{
int a[ROWS][COLS] = { { 5, 10, 5} , { 6, 4, 2 } };
int b[ROWS][COLS] = { { 2, 3, 4} , { 10, 11, 12 } };
add(a, b);
return 0;
}
EDIT: Unless you want to specify the dimensions at runtime, in which case you have to use a flat array and do the 2D array arithmetic yourself:
/* Store sum of matrix a and b in a */
void add(int rows, int cols, int a[], int b[])
{
int i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
a[i * cols + j] += b[i * cols + j];
}
#caf has shown a good code example.
I'd like to point out that:
I assigned a pointer to the base
address of my matrix. (for eg: int
*x=a[0][0],*y=b[0][0]).
You are not assining a pointer to the base of the matrix. What this does is assign to the value pointed by x and y, the base value in a and b respectively.
The right way would be
int (*x)[] = a;
int (*y)[] = b;
or alternatively
int *x = &a[0][0];
int *y = &b[0][0];