0

I don't understand clearly what happens when you cast allocated memory through double pointer, as:

char **ptr;
ptr=(char *)malloc(sizeof(char)*value); 
for(i=0;i<value;i++)
   ptr[i]=(char **)malloc(sizeof(char *)*another_value);

During the first call of malloc, a void * is casted to char * so, i can access it using *(ptr+i), but during the second call of malloc i don't understand why i need to cast void * to char **, would not be enough to cast it to char * ?

Luca
  • 55
  • 7

5 Answers5

5

Casting in the above snippet makes no sense. Do not cast return value of malloc. And allocation is wrong too. It should be like:

ptr = malloc(sizeof(char*)*value);  

and

ptr[i] = malloc(another_value); 
Community
  • 1
  • 1
haccks
  • 104,019
  • 25
  • 176
  • 264
  • 2
    I think you want to add `* value` to the first `malloc()` (to be consistent with what's in the question); also, worth pointing out that `sizeof(char)` is redundant since the size is returned in `char`s... – psmears Dec 31 '14 at 17:17
  • @psmears; You are right. No need of `sizeof(char)` here. – haccks Dec 31 '14 at 17:19
  • 2
    Just to be 100% clear, the downvoter wasn't me (I upvoted after your edit!). I'd also be interested to know the reasons for the downvote... – psmears Dec 31 '14 at 18:06
3

Both are wrong.

Both casts are unnecessary as a void pointer (malloc returns void*) is compatible with any other data pointer.

See: http://c-faq.com/malloc/cast.html

P.P
  • 117,907
  • 20
  • 175
  • 238
0

You are doing it wrong.

First of all no need to cast malloc() Please take a look at the changes below.

Since the return type of malloc() is void * no need to cast malloc()

char **ptr = (char **)malloc(sizeof(char *)*another_value);

for(i=0;i<value;i++)
ptr[i]=(char *)malloc(sizeof(char)*value);

Remove cast and have

char **ptr = malloc(sizeof(char *)*another_value);

for(i=0;i<value;i++)
ptr[i]= malloc(sizeof(char)*value);
Gopi
  • 19,784
  • 4
  • 24
  • 36
  • Not my downvote, but you should be using `sizeof(char*)*value` instead of `sizeof(char*)*another_value`. – Spikatrix Jul 20 '15 at 09:12
0

The right way is

char **ptr;
ptr = malloc(sizeof(char *) * value); // value pointers of char
for(i=0;i<value;i++)
    ptr[i] = malloc(sizeof(char)*another_value); // another_value of chars

your code compiled because void * is automatically converted to any pointer type, but if you turn on warnings, the compiler would notify you that you are assigning pointers of incompatible types.

Without the casts however no warning will be issued.

Another thing, sizeof(char) != sizeof(char *) you need value pointers to char and then each pointer will be pointing to another_value array of chars.

So the first call to malloc you have to allocate value * sizeof(pointer), the syntax for that is

value * sizeof(char *)
/*                  ^ see the star here. */

and then you don't need sizeof(char) since it's 1, the following is correct

char **ptr;
ptr = malloc(sizeof(char *) * value); // value pointers of char
for(i=0;i<value;i++)
    ptr[i] = malloc(another_value); // another_value of chars
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
-3

It is a good idea to cast the void pointer returned by malloc to the type of the destination pointer. In this case you can find an error similar to the error in your code snippet.

char **ptr;
ptr=(char *)malloc(sizeof(char)*value); 

Here variable ptr has type char ** while the right side of the assignment statement has type char * due to the casting. So the compiler shall issue an error (more precisely a diagnostic message) because there is no implicit conversion from char *. to char **

By the way by this reason in C++ there is not allowed to assign a pointer of type void * to pointers of other types because such a code is unsafe.

The other reason to cast the void pointer returned by malloc is to make your code self-documented. Consider for example the following statement

p = malloc( sizeof( *p ) );

Here it is difficult to understand what is the type of memory is allocated. It would be much better to write for example

p = ( double * )malloc( sizeof( *p ) );

In this case the statement is more clear and you need not to scroll a big program listing that to determine what is the type of p.

Take into account that a good program is a program where each statement provides you as much information as you need that to understand what the statement is trying to do and what types of variables envolved in expressions..

There is one more reason to cast the pointer returned by malloc. If you will try to compile your code with a C++ compiler then it will issue numerous errors for each using of malloc without casting. When you will transfer your code from C to C++ you will estimate the value of such casting.

Here is the correct using of malloc for your example

char **ptr;

ptr = ( char ** )malloc( value * sizeof( char * ) ); 
for ( i = 0; i < value; i++ )
   ptr[i] = ( char * )malloc( another_value * sizeof( char ) );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 5
    There is no need to be offensive, if I didn't comment you it would be ok to be angry. But I commented since this has been very much discussed everywhere and the resulting conclusion is that it's [not a good idea](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) to cast from `void *`, it's not wrong either. – Iharob Al Asimi Dec 31 '14 at 17:31
  • 2
    If you are such a high qualified programmer why did you write this "_o the compiler shall issue an error because there is no implicit conversion from char *_"? did you try to compile that? Are you sure it's an error? it's just a warning. – Iharob Al Asimi Dec 31 '14 at 17:36
  • @iharob No, I did not try. There is no any need to try to compile the code. Take into account that compilers have bugs or their own "extensions" that contradict the C Standard. In any case the compiler shall issue a diagnostic message. But in any case it is in essence an error. – Vlad from Moscow Dec 31 '14 at 17:39
  • You are right with the last part. But you are very wrong with the rest, because it's not necessary to offend any one and your are expressing your opinion so you can say _`I think it's a good Idea to cast ...`_, I actually think that SO should warn the moderators when someone uses words like _`idiot`_... It's not necessary at all. – Iharob Al Asimi Dec 31 '14 at 17:44
  • @VladfromMoscow; Didn't downvoted but for your information: **C11-7.22.3.4:** `The malloc function returns either a null pointer or a pointer to the allocated space.` You can also see their that there is no casting before `malloc` in the entire document. – haccks Dec 31 '14 at 18:14
  • @haccks And what? Most of code examples in the C Standard are examples how code shall not be written. The task of the code examples in the C Standard is not to show how the code shall be written in projects. Their task is to show peculiarities of the language. – Vlad from Moscow Dec 31 '14 at 18:17
  • @VladfromMoscow; *The task of code examples in the C Standard is not to show how the code shall be written in projects.*: Disagree. – haccks Dec 31 '14 at 18:21
  • @haccks I advice you to read my answer one more and think about it. It will be more helpful for you then reading of references you gave. – Vlad from Moscow Dec 31 '14 at 18:22
  • @VladfromMoscow; I didn't read you question at first. But after marked as accepted, the 3 downvotes tempted me to read the answer. I read your complete answer and I concluded that you may seem to be relating with the return value of `malloc` in C++ with C. In C++, return value of `malloc` must be casted. – haccks Dec 31 '14 at 18:26
  • @haccks First of all C++ improved some weak points of C. But the main reason is not that I follow C++ . The main reason is to write good safe and clear code. – Vlad from Moscow Dec 31 '14 at 18:31
  • @haccks If you may use some language constructions it does not mean that you should use them. – Vlad from Moscow Dec 31 '14 at 18:33