0

Im trying to crate a two dimensional array of FILE pointer

when I did this:

FILE *pFile = OpenFile(fileName);
FILE **lossArr  =   (FILE**)malloc(sizeof(FILE*) * i * j);

lossArr [0] =  pFile;
fputs ("some text\n",(lossArr[0]));  

it worked fine,

but when I added * to make it two dimensional array:

FILE *pFile = OpenFile(fileName);
FILE ***lossArr =   (FILE**)malloc(sizeof(FILE*) * i * j);

lossArr[0][0] =  pFile;
fputs ("some text\n",(lossArr[0][0]));  

I got Access violation writing location 0xcdcdcdcd.

I saw declaration of two dimensional array with malloc, but I would like to know what is the way to create two dimensional array of FILE pointers? what is wrong with my code.

thanks in advanced!

user1673206
  • 1,671
  • 1
  • 23
  • 43
  • To assist you writing code you could do `typedef FILE *FILEPOINTER;` and then use a standard recipe for allocating a 2D array of FILEPOINTER (there are hundreds of threads of that on SO). Normally I would not recommend pointer typedefs , but since `FILE *` is opaque , this situation is an exception. – M.M Aug 28 '14 at 10:10
  • You should decide which language you're using. If it's C++, then use the C++ library (streams, `vector`, etc.) and save yourself the pain (and long debugging sessions) of manual memory wrangling. If it's C, then use a C compiler so you don't need those horrible casts. This code is the worst of both languages, and will give you nightmares if you continue like this. – Mike Seymour Aug 28 '14 at 10:42

5 Answers5

2

First. You should allocate memory for each raw in array

int ii;
typedef FILE * FILE_PTR;
FILE_PTR ** lossArr = (FILE_PTR**)malloc( sizeof( FILE_PTR* ) * i );
for ( ii = 0; ii < i; ii++ ) {
    lossArr[ ii ] = (FILE_PTR*)malloc( sizeof( FILE_PTR ) * j );
}
// now you can use lossArr[ x ][ y ], where x = 0..i-1, y = 0..j-1

Second. This is C, but not C++. If you can use C++, then use std::vector

borisbn
  • 4,988
  • 25
  • 42
  • In C, [don't cast malloc](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) ! Other than that, great answer – M.M Aug 28 '14 at 10:12
0

Your approach is similar to that presented here, which uses an array of pointer-to-pointers, and your code is crashing as you haven't allocated the second dimension of pointers.

You could continue your approach by calculating the index into lossArr yourself, treating a single-dimension array as two-dimensional using a macro:

#define INDEX_FOR(r, c) r * i + c

FILE** lossArr = (FILE**)malloc(sizeof(FILE*) * i * j);
lossArr[INDEX_FOR(0, 0)] = pFile;

However using std::array is better including using fstream instead of FILE*:

std::array<std::array<std::fstream, j>, i> lossArr;
lossArr[0][0] =  file;
trojanfoe
  • 120,358
  • 21
  • 212
  • 242
  • 1
    Your malloc is wrong , the `sizeof` expression must refer to the size of the thing being pointed to, not the size of the pointer – M.M Aug 28 '14 at 10:11
  • @MattMcNabb Not true; the OP wants an array of `FILE*` not `FILE`. – trojanfoe Aug 28 '14 at 10:14
  • My statement is true in all situations. If you are allocating for a `T *` then you must use `sizeof(T)` or equivalent as the size of each element. If `T` is `FILE*` then you must use a `FILE **` to point to what you've allocated. – M.M Aug 28 '14 at 10:16
  • @MattMcNabb Nope again; my first example creates an artificial two-dimensional array from a single-dimension array (hence the use of the macro). – trojanfoe Aug 28 '14 at 10:17
  • Your code doesn't even compile, `lossArr[x]` has type `FILE` and `pFile` has type `FILE *`. – M.M Aug 28 '14 at 10:18
  • @MattMcNabb What are you talking about? – trojanfoe Aug 28 '14 at 10:19
  • You are mallocing the wrong amount of memory, and your code doesn't compile. – M.M Aug 28 '14 at 10:21
  • `malloc(sizeof(FILE*) * i * j)`: this should be kept as `FILE**` – dragosht Aug 28 '14 at 10:21
  • Yep; fixed. Bottom line, though, is use `std::array`. – trojanfoe Aug 28 '14 at 10:26
0

Please look at this in reference to your problem:

int a[5] = {1,2,3,4,5};
a[1] = a[4];

is equal to

int b[5] = {1,2,3,4,5};
int *a = b;
a[1] = a[4];

but

int a[2][2] = { {1,2}, {3,4} };
a[0][0] = a[1][1];

is not equal to

int b[2][2] = { {1,2}, {3,4} };
int **a = b;  // compilation error
a[0][0] = a[1][1]; // runtime error

but

int b[2][2] = { {1,2}, {3,4} };
int *a = b;
a[0] = a[3];

will work

Pointers can't point to multidimensional arrays insted they point to arryas of pointers. If you point a pointer to multidimensional array it will flatten an array.

int **a;

mean pointer to int pointer not pointer to 2d int array

Logman
  • 4,031
  • 1
  • 23
  • 35
0

Doing this:

FILE **lossArr  =   (FILE**)malloc(sizeof(FILE*) * i * j);

Only gets you a pointer to a space of i*j FILE pointers.

This:

FILE ***lossArr =   (FILE**)malloc(sizeof(FILE*) * i * j);

is even worse - you convert a FILE** to a FILE***.

Do this instead:

int k;
FILE ***lossArr  =   (FILE***)malloc(sizeof(FILE**) * i);
for (k = 0; k < i; k++) {
    lossArr[i] = (FILE**)malloc(sizeof(FILE*) * j);
}

Note: don't forget to free memory afterwards

for (k = 0; k < i; k++) {
    free(lossArr[i]);
}
free(lossArr);

Note2: If in C++ as the tag suggests, you may consider using std::vector to avoid all this pointer wizardry

dragosht
  • 3,237
  • 2
  • 23
  • 32
  • 1
    You're not allowed to malloc your own `FILE` structures, you can only use pointers returned by functions that return a `FILE*`. The type must be treated as opaque and non-movable. – M.M Aug 28 '14 at 10:07
0

FILE*** lossArr is an array of array of file pointers. To initialize it, you first have to allocate an array of array pointers as in

lossArr = (FILE***) malloc( sizeof(FILE**) * i);

Then, you have to initialize each second-level array

for (int ii = 0; ii < i; ii++) lossArr[ii] = (FILE**) malloc( sizeof(FILE*) * j);

Only now is lossArr ready to be used.

My tip: Use 1D arrays and index them with i*ii + jj. They are easier to initialize and destroy, and more efficient!

gTcV
  • 2,446
  • 1
  • 15
  • 32