0

I'm a beginner in C and I'm facing this problem: I created a function based on the fast matrix allocation method (Oliveira and Stewart, "Writing Scientific Software", pag. 94) and I want to use it for any data type. I therefore changed it a bit as follows:

void ** malloc_array2d(size_t m, size_t n){

  /* pointer to array of pointers */
  void ** pointer;
  size_t i;
  /* allocate pointer array of length m */
  pointer = malloc(m*sizeof(void));
  if(pointer == NULL){
    return NULL;
  }
  /* allocate storage for m*n entries */
  pointer[0] = malloc(m*n*sizeof(void));
  if (pointer[0] == NULL) {
    free(pointer);
    return NULL;
  }
  /* set the pointers */
  for (i = 1; i < m; i++) {
    pointer[i] = pointer[0] + i*n;
  }

return pointer;
}

but I get segmentation fault.

The question is: how to allow for memory allocation of different data type, since sizeof(void) is not working (and indeed it returns just 1)? Any feedback is really appreciated. Thanks.

Mattia Paterna
  • 1,268
  • 3
  • 15
  • 31
  • 3
    What is the sound of one hand clapping? It's about the same philosophical question as asking what the size of no type is. You are probably supposed to allocate some number of *bytes*. – Some programmer dude Oct 23 '16 at 17:42
  • 3
    You'll have to tell `malloc_array2d` the size of the element type, because it can't know if you don't. You'll end up with something like `void **malloc_array2d(size_t m, size_t n, size_t element_size);`. –  Oct 23 '16 at 17:43
  • MSVC says of `sizeof(void)` "warning C4034: sizeof returns 0". Pay heed to such warnings. – Weather Vane Oct 23 '16 at 17:44
  • Where did you find a compiler that compiles sizeof (void)? void is an incomplete type that cannot be completed. sizeof (void) shouldn't compile. – gnasher729 Oct 23 '16 at 17:45
  • @Someprogrammerdude: sure. I used _sizeof(void)_ because I thought it was possible some kind of substitution. When using malloc, for instance, I'm taking a void pointer and then I'm casting it to my desired data type (or I was taught so). – Mattia Paterna Oct 23 '16 at 17:46
  • 1
    `sizeof(void)` is invalid. (return 1 as GCC extension) – BLUEPIXY Oct 23 '16 at 17:46
  • 1
    What does the return type of `malloc` have to do with `sizeof(void)`? a `void*` is not the same as `void`. Also what do you mean by "some kind of substitution"? – UnholySheep Oct 23 '16 at 17:48
  • @Rhymoid I'll try with this, thanks! and sorry for the poor question, I'm still at the beginning. – Mattia Paterna Oct 23 '16 at 17:48
  • That is because pointers are (usually) the same size regardless of the type pointed to. Whereas the types themselves have various sizes. – Weather Vane Oct 23 '16 at 17:49
  • @UnholySheep some `malloc` behaviour alike - I cast from void * to the data type I want. sorry for the poorness in my language. – Mattia Paterna Oct 23 '16 at 17:51
  • @WeatherVane thanks for the explanation! – Mattia Paterna Oct 23 '16 at 17:52
  • 1
    Your question may already have an answer [here](http://stackoverflow.com/a/28259072/1892179). – Theodoros Chatzigiannakis Oct 23 '16 at 17:53
  • @Theodoros ja, actually my question is not which size if void, but how to allow for allocating arrays of different data types and, therefore, how to let that `malloc` know about my chosen data type. But that answer really helped me in understanding more about it, thank you! – Mattia Paterna Oct 23 '16 at 18:02
  • `sizeof(void)` is [invalid](http://ideone.com/X1TOlG) as far as C goes ans should be blocked by a compiler. What compiler are you using? – n. m. could be an AI Oct 23 '16 at 18:10
  • if I code `printf("sizeof(void) = %zu\n", sizeof(void));` I get 1. I'm using gcc to compile my code on Mac platform - should be GNU C, isn't it? – Mattia Paterna Oct 23 '16 at 18:14
  • @n.m. I read also [here](https://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html) – Mattia Paterna Oct 23 '16 at 18:16
  • As I'm observing right now, line **pointer = malloc(m*sizeof(something))** will be incorrect, due **pointer** should not going to reference a block of memory of m slices of sizeof(something) each one, but should reference a block of memory with different new pointer addresses. I think transformation from your example it's not correct. – DvTr Oct 23 '16 at 18:24
  • Don't. Language extensions should not be used unless absolutely necessary. In this case, it is not necessary. – n. m. could be an AI Oct 23 '16 at 18:26
  • @DvTr that is correct, my aim is to create an array of pointers and set the pointers then so to have a _row-major order_ (Oliveira and Stewart, chapter 8, p. 92) – Mattia Paterna Oct 23 '16 at 18:39
  • Then, your pointer not should be allocated to m*sizeof(datatype), but instead to m*sizeof(datatype *). Should then pass sizeof(datatype *) as parameter as well... – DvTr Oct 23 '16 at 18:49
  • There is no matrix (aka 2D array) in your code, nor something which can point to one. – too honest for this site Oct 23 '16 at 19:22
  • @Olaf could you please explain why? If I allocate memory for a number of entries m * n, I should get a matrix. – Mattia Paterna Oct 23 '16 at 22:31
  • 1
    You should do some research then! Just because you call it like that (or someone else did), it is not true. There are quite some ppl having missconception about this, so your falut is understandable. Something like `whatever_type **` cannot represent a 2D array. If you need a 2D array, use one! Not only that allocation is much easier and straight-forward, but also freeing and usage. There are enough postings how to do it right, just search for them. – too honest for this site Oct 23 '16 at 22:36
  • I will. For future, if I write something like _I'm beginner_ that means I can't know everything. And, if I do that, probably that means I've been taught by someone to do that way. I also brought references. I should trust people, especially my professors. Thanks for inspiration. – Mattia Paterna Oct 23 '16 at 22:44
  • or maybe, @Olaf, you talk about something like `whatever_type my_array[m][n]`. Because that is the only other method that I know for now. I completely agree with you that it works pretty straightforward. Unfortunately, I faced to different challenges and one of those was creating an array like that. It has been motivated to me as a way to make it faster, avoiding memory leaks and being efficient in time and memory. Of course, I hope to learn more about it. – Mattia Paterna Oct 23 '16 at 22:53
  • So you know what a 2D array is. Good for you. And why don't you use it then? (btw: this is the **only** correct way for a 2D array. There is a variation to use a pointer to a 1D array, which is exactly what the 2D array decays to for **most** operations, including function parameters. – too honest for this site Oct 23 '16 at 22:58
  • the answer is the easiest one: I **have to** use that way this time. next time, I'll get back to my beloved `array[m][n]`. but good to know. thanks again! – Mattia Paterna Oct 23 '16 at 23:01

3 Answers3

2

void is not the matching type of what pointer references. pointer references void *, not void.

Avoid the mistake in the future by not coding the size of the referenced type, but coding the size of the de-referenced pointer.

// pointer = malloc(m*sizeof(void));
pointer = malloc(sizeof *pointer * m);

For the next allocation, sizeof(void) * m *n is not well defined. Code needs a new approach.

// pointer[0] = malloc(m*n*sizeof(void));

To allocate for various types, pass in the size of the data type.

void ** malloc_array2d(size_t m, size_t n, size_t data_size){
  ...
  unsigned char *p = malloc(data_size * m *n);
  ...
  for (i = 0; i < m; i++) {
    pointer[i] = p + i*n*data_size;
  }
Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

Sizeof returns the quantity of bytes that every datatype are. 1 for byte, 2 for int16, 4 for int32, etc... You can then pass it as parameter, with any kind of problem, as at the moment of use of malloc_2darray function you should know final datatype to map to.

Note that always you use your malloc_2darray function you should cast to final datatype pointer for a correct interpretation of returned pointers.

DvTr
  • 347
  • 1
  • 5
  • What do you mean "cast to final datatype"? Are you saying he should cast the return of `malloc`? Because that is definitely a huge **NO** and should **not** be done! – UnholySheep Oct 23 '16 at 18:02
  • hmm, that sounds interesting since I was thought to do this way. I was reading something about **not** to cast before. – Mattia Paterna Oct 23 '16 at 18:03
  • No, I meaning **to cast the use of malloc_2darray function**, the one he had created. If not, it's very possible that program dont know how to work with pointers allocated with malloc_2darray (ex; char **p = malloc_2dArray(..,...); will be assigned here to **p a (void **). What will happen if next lines are **p++ or similar? Will it increment a byte the pointer? Two? No position increment? the best thing to avoid this is char **p = (char **)malloc_2darray(..,..) – DvTr Oct 23 '16 at 18:05
-1

Firstly the value of the sizeof(void) is always 1, here void refers to pointer memory allocation for untyped datatype. I don't think any other datatype takes that much less memory. Well int, float, etc consumes more bit of data. If you want the value of sizeof() to return 1, You can just manually specify the size in malloc() function instead of using sizeof() functionalities along with different datatypes.

Aniruddha Alek
  • 227
  • 3
  • 10