0

is there a simple one liner I can use in C to allocate arrays in (pointer of arrays)

This line creates 10 pointers of arrays

char *out[10];

I can't do this

char *out[100]=(char[10][100])malloc(sizeof(char)*10*100);

error: cast specifies array type

same error with

 char *out[10]=(char*[10])malloc(sizeof(char)*10*100);

do I need to do it in loop like this

int main()
{   
  
  
  char *out[10];
  int x=0;
  while(x<10)
  {
     *(out+x)=malloc(sizeof(char)*100);// is this line correct?
      x++;
  }
  *out[0]='x';
   printf("%c\n",out[0][0]);
   free(out);
   return 0;
}

but this cause warning that

req.c:75:3: warning: attempt to free a non-heap object ‘out’ [-Wfree-nonheap-object]
   75 |   free(out);

so do I need to allocate and free each array in (array of pointers) in loop

Can't I do allocation and free arrays in array of pointer in one line instead of loop?

or is there anything thing in my loop wrong too

user786
  • 3,902
  • 4
  • 40
  • 72
  • 2
    You [should not cast the result of `malloc`](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – Some programmer dude Oct 13 '21 at 07:46
  • As for part of your problem, `char *out[10];` defines `out` as an array of pointers, not a pointer to an array. You should not allocate the array itself, but rather the elements in it. As in `out[0] = malloc(some_length)` And you should call `free` with the pointers returned by `malloc`. `out` is not a pointer, and it's not allocated with `malloc`. – Some programmer dude Oct 13 '21 at 07:47
  • @Someprogrammerdude `out[0] = malloc(some_length)` so is this will allocate first array? – user786 Oct 13 '21 at 07:48
  • Given that you have `char *out[10];` the answer to your question is: No, there is no one liner that can allocate memory and assign values to all 10 char-pointers. – Support Ukraine Oct 13 '21 at 10:12

3 Answers3

4

To allocate an array of pointers to strings, you need to do:

char** out = malloc(sizeof(char*[10]));

The whole point of using this form is that each pointer in that array of pointers can be allocated with individual size, as is common with strings. So it doesn't make sense to allocate such with a "one-liner", or you are using the wrong type for the task.

In case you don't need individual sizes but are rather looking for a char [10][100] 2D array with static size, then the correct way to allocate such is:

char (*out)[100] = malloc(sizeof(char[10][100]));
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Is there a size limit I can assume of each line in http request. This question was for that thing. So that's why I need 10 array of 100 size each like (*out)[100]=... to contain 10 lines completely – user786 Oct 13 '21 at 08:06
  • you could consider calloc: `char (*out)[100] = calloc(10, sizeof *out);`. It avoids repeating two crucial entities: number `100` and type `char` – tstanisl Oct 13 '21 at 08:11
  • @tstanisl what do u mean. can u show with explanation – user786 Oct 13 '21 at 08:49
  • @user786, I mean that if one day you change `100` to `200` you will have to change it in two places. With my suggestion one will have to change it in only one place. – tstanisl Oct 13 '21 at 08:51
  • @user786 "Is there a size limit I can assume of each line in http request." I have no idea, that sounds like a decent new question to ask. – Lundin Oct 13 '21 at 08:53
  • 1
    @tstanisl Obviously in a real-world application these should be named constants/variables rather than magic numbers. But I generally disagree, the chance of screwing up the malloc call by being "smart" is much greater than the chance of slipping on a key when doing a little bit of code repetition. And "being smart" bugs are generally much harder to track down than typo bugs. – Lundin Oct 13 '21 at 08:56
  • And generally, if you have no clue what you are doing when typing out the malloc call, then no "clever" tricks in the world will save you. If you can remember to type out `sizeof *out` you could as well remember to double check all types and sizes. KISS > DRY, always. – Lundin Oct 13 '21 at 08:57
  • @Lundin, it's a lesser problem when the declaration and malloc are within the same line. But when those are separated, or malloc happens in different conditional branches then `sizeof *out` will start to pay off – tstanisl Oct 13 '21 at 09:33
  • @Lundin why this line `printf("%s\n",*out[1]);` gives `malloc(): corrupted top size` if I do `char (*out)[100] = malloc(sizeof(char[10][100]));` if its correct. Is it because no line termination? or what – user786 Oct 13 '21 at 10:25
  • @user786 This is an array of 10 strings. `out[1]` gives the second string. `*out[1]` gives the first character of the second string. You need to do `out[1]` if printing with `%s`. – Lundin Oct 13 '21 at 11:21
  • @user786: You can ignore Lundin’s comments about expressing the size of the allocation. Using `sizeof *p` or `N * sizeof *p`, where `p` is the pointer being assigned or initialized and `N` is the number of things you want, is a simple and well-known idiom. – Eric Postpischil Oct 13 '21 at 11:37
  • The point here: I was once an admirer of the "being clever" malloc trick too, which works just fine and is even idiomatic for trivial cases like `int* arr = malloc(n * sizeof *arr);`. But after watching countless fiasco examples of this trick on SO for the past 10 years, I learnt that this style does not scale well when dealing with multiple dimensions or with function parameters (where the array has decayed into a pointer). Then all it does is creating subtle but severe bugs with too little memory allocated. – Lundin Oct 13 '21 at 11:58
  • @Lundin Can u please also show how to pass `out` and receive in another function and populate containing arrays in called function and get it print updated arrays in calling function after function call? – user786 Oct 13 '21 at 13:22
  • @user786 There is an example similar to that at the bottom of the answer here: [Correctly allocating multi-dimensional arrays](https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays) – Lundin Oct 13 '21 at 13:27
  • @Lundin can you give an example of a fiasco of the "clever malloc trick"? – tstanisl Oct 13 '21 at 14:56
1

You can allocate the full array in one single step and have pointers inside that array:

char *out[10];

data = malloc(100);   //sizeof(char) is 1 by definition
for (int x=0; x<10; x++) {
    out[i] = data + x * 10;
}
*out[0] = 'x';
printf("%c\n",out[0][0]);
free(data);           // you must free what has been allocated
tstanisl
  • 13,520
  • 2
  • 25
  • 40
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • Is there a size limit I can assume of each line in http request in server. This question was for that thing. So that's why I need 10 array of 100 size each like (*out)[10]=... to contain 10 lines completely – user786 Oct 13 '21 at 08:09
  • 1
    I suggest to use `free(out[0]);`, there would be no need to keep `data` around – tstanisl Oct 13 '21 at 08:13
0
int i;
char** out = (char**)malloc(sizeof(char*)*10);
for(i = 0; i<10;i++)
   out[i] = (char*)malloc(sizeof(char)*100);
out[1][1] = 'a';

OR with same dimensions

#include <stdio.h>
#include <stdlib.h>
 
void main()
{
    int r = 10, c = 100; //Taking number of Rows and Columns
    char *ptr, count = 0, i;
    ptr = (char*)malloc((r * c) * sizeof(char)); //Dynamically Allocating Memory
    for (i = 0; i < r * c; i++)
    {
        ptr[i] = i + 1; //Giving value to the pointer and simultaneously printing it.
        printf("%c ", ptr[i]);
        if ((i + 1) % c == 0)
        {
            printf("\n");
        }
    }
    free(ptr);
}
One Man Crew
  • 9,420
  • 2
  • 42
  • 51
  • There's no reason to use archaic "mangled 2D arrays" in modern C. That's how we coded in the 1990s, but calculating the index manually is cumbersome, error prone and hard to read. Instead you could use a pointer to VLA as `char (*arr)[c] = malloc(sizeof(char[r][c]));` and access it as `arr[i][j]`. – Lundin Oct 13 '21 at 08:02