2

I would like to allocate 2D array and I am considering two possibilities (avr-gcc on Arduio):

A:

int **arr = new int*[5];
for(int i = 0 ; i < 5 ; i++){
   arr[i] = new int[10];
}

B:

 int **arr = malloc(5 * sizeof(int *));
 for(int i = 0 ; i < 5 ; i++) {
    arr [i] = malloc(10* sizeof(int))
 } 

Is there any difference between A and B? Would the compiler create the same byte code in those two cases (arv-gcc)?

Maciej Miklas
  • 3,305
  • 4
  • 27
  • 52

3 Answers3

7

In C, you can't allocate memory by new, because there is no such thing. For C++, you may prefer new for couple of reasons such as:

  • exceptions (unless you add (std::nothrow) explicitly)
  • initializer lists (since C++11)
  • better safety as it returns pointer of proper type (specifically not void *)
  • cleaner syntax (but that is purely subjective)

See In what cases do I use malloc and/or new? for more discussion on that matter.

If you want to allocate a two-dimensional array and the rightmost size is known at compile-time (i.e. it is a constant expression - constexpr), then you don't need to loop over.

New in C++

int (*arr)[10] = new int [2][10];

If you want it to be pre-set with zeros (that is, like std::calloc), then use:

int (*arr)[10] = new int [2][10]{0}; // C++11
int (*arr)[10] = new int [2][10]();  // C++03

Just like for any arrays allocated by new[], there is a corresponding delete[] operator to free it:

delete[] arr;

Malloc in C and C++

int (*arr)[10] = malloc(5 * sizeof(*arr));

This allocates array, that is like arr[5][10] (only in sense of indices).

To access its elements in both simply use:

arr[a][b]

To free it, you basically do:

free(arr);

In C++ you additionally need to take care of cast and possibly qualify it with std, so it's std::malloc (especially if includes cstdlib, as stdlib.h header is deprecated in C++ Standard):

const int N = 10;

int (*arr)[N] =
    static_cast<int (*)[N]>(std::malloc(5 * sizeof(*arr)));

but I don't think that you will like it.

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
Grzegorz Szpetkowski
  • 36,988
  • 6
  • 90
  • 137
  • 2
    In C++ you would need to cast malloc, unfortunately – M.M Jul 20 '15 at 08:46
  • 1
    This example allocates a pointer to a 2D array. This will probably perform better than the OP's example of pointers to pointer since all the memory allocated is together. If you need pointers to pointers you can always construct your pointer array to point into your 2D array. – doron Jul 20 '15 at 10:15
  • this does not work in Arduino Studio . It will throw an error of "Compilation error: invalid conversion from 'void*' to 'int (*)[10]' [-fpermissive]" – Miguel Tomás Jan 03 '23 at 17:06
4

If you're using a C++ compiler (and Arduino sketches are C++), you should probably prefer new. It's unlikely to matter for doing a simple int array but I'd leave C legacy stuff only for code that has to run in a C environment.

There's absolutely no reason nowadays for C+ programmers (that curious breed of programmer which never whole-heartedly transitions from C to C++) to exist :-)

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • Like the C+ programmers tutorial... perhaps you could post a follow-up, explaining why `inline` shouldn't be preferred over macro's that expand to other macro's that expand to some other expression – Elias Van Ootegem Jul 20 '15 at 09:40
  • @EliasVanOotegem, consider it done, feel free to leave a comment (over there rather than here) if it doesn't meet your expectations. – paxdiablo Jul 20 '15 at 12:18
  • Comment posted, added some example of the type of macro's I've stumbled on in the past – Elias Van Ootegem Jul 20 '15 at 14:07
2

A and B are basically equivalent.

The compiler may or may not create the same code (not byte code BTW). But often using the new operator simply boils down to a call to malloc. To find out, compile your program with gcc -S and have a look at the assembly output.

But for c++ programs you should prefer new to malloc.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115