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?

3
  • 1
    For your last question, you can refer to this question Commented Oct 31, 2019 at 9: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. Commented Oct 31, 2019 at 9:32
  • Incidentally, casting malloc() is discouraged in modern C, since it can force code to compile even if #include <stdlib.h (the header that declares malloc() and friends) and the common result is then undefined behaviour. It was only ever necessary in (very old) versions of C that predated introduction of the void pointer into the language (so malloc() returned char *). Commented Oct 31, 2019 at 10:31

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

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 - 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.
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;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.