0

I need some explanation for some commands in this particular piece of code:

#inlcude <stdlib.h>
#define PTRS 5

char *p[PTRS];

size_t nbytes = 10;
int i;
/* Allocating memory */
for (i=0; i<PTRS; i++){
    printf("malloc of %10lu bytes ", nbytes);

    if ((p[i] = (char *)malloc(nbytes)) == NULL){
        printf("failed\n");
    } else {
        printf("succeeded\n");
    nbytes *= 100;
}
/* Free the memory allocated */
for (i=0; i<PTRS; i++){
    if(p[i]){
        free(p[i]);
        p[i] = NULL;
    }
}

First one is
char *p[PTRS];
Does this line declare a pointer to an array or does it declare an array of pointers to char?
p[i] = (char *)malloc(nbytes) I understand that as i increases, p[i] will contain a pointer to the allocated memory called by malloc if it's successfully processed, and p[i] will beNULL` if no such memory can be prepared.
Second one is

if (p[i]){
    free(p[i]);
    p[i] = NULL;
}

This only frees memory if p[i] has any value (in this case a pointer to the memory). What happens if we remove if(p[i]) and only use free(p[i] and p[i] = NULL? Can we free a NULL pointer?

NVA
  • 37
  • 4
  • 1
    For your last question, you can refer to [this question](https://stackoverflow.com/questions/1938735/does-freeptr-where-ptr-is-null-corrupt-memory) – KagurazakaKotori Oct 31 '19 at 09:32
  • 2
    Given `size_t nbytes`, your `printf("malloc of %10lu bytes ", nbytes);` invokes undefined behavior. The proper format string for `size_t` is `%zu`. – Andrew Henle Oct 31 '19 at 09:32
  • Incidentally, casting `malloc()` is discouraged in modern C, since it can force code to compile even if `#include – Peter Oct 31 '19 at 10:31

2 Answers2

2
char *p[PTRS];

is equivalent to

char *(p[PTRS]);

i.e. it's an array of pointers, not a pointer to an array. A pointer to an array would be e.g.

char (*p)[PTRS];

The clockwise/spiral rule could be helpful in deciphering declarations. As would using resource such as https://cdecl.org.


And you can pass a NULL pointer to free (it's a no-op) so the check isn't needed really.

Depending on the further use of p, the p[i] = NULL assignment might not be needed either.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Thank you! And also I just read that `free(NULL)` used to cause some problems on old systems, that's why they added the check. – NVA Oct 31 '19 at 09:36
  • 1
    @NVA - That's only a concern if you've managed to find VERY old compilers and library. Even K&R C (first edition was in 1978, from memory, which predated ratification of the first C standard by over a decade) specified that `free(NULL)` had no effect. There were a few libraries before K&R first edition which would crash on `free(NULL)` but those were considered bugs even by their vendors/developers so you'd be hard pressed to find a C compiler and library with that behaviour. – Peter Oct 31 '19 at 10:28
1

I understand that as i increases, p[i] will contain a pointer to the allocated memory called by malloc

So if you understand this when it means that p[i] being an element of an array has the type char * because at least in the program there is explicit casting to this type of themalloc call in the if statement

 if ((p[i] = (char *)malloc(nbytes)) == NULL){

So this declaration

char *p[PTRS];

declares an array of PTRS elements with the tyoe char *. I advice to write such a declarations like

char * p[PTRS];

inserting a blank after the character '*'.

You may rewrite the declaration also the following way

char * ( p[PTRS] );

A pointer to an array of PTRS elements of the type char is declared the following way.

char ( *p )[PTRS];

Can we free a NULL pointer?

More precisely it would be said may we use the function free with a null-pointer because we are not freeing a null pointer itself that in the context of your example has the automatic storage duration.

The answer is yes we may. A call of the function with a null pointer will have neither affect and is safe.

Thus this loop

for (i=0; i<PTRS; i++){
    if(p[i]){
        free(p[i]);
        p[i] = NULL;
    }
}

may be rewritten like

for (i=0; i<PTRS; i++){
    free(p[i]);
    p[i] = NULL;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335