Doubt with char* and char[]

K

Kamui Shirow

Hello!

I will write a snippet to illustrate my doubt:

snippet 1:
void foo( int l )
{
char* tmp;
tmp = (char*) malloc( l * sizeof( char ) );

// DO SOMETHING

free( tmp );

}

snippet 2:
void foo( int l )
{
char tmp[l];

// DO SOMETHING

}

What is the difference in advantage if I use snippet 1 or 2?

Thanks in advance!
 
J

Joachim Schmitz

Kamui Shirow said:
Hello!

I will write a snippet to illustrate my doubt:

snippet 1:
void foo( int l )
{
char* tmp;
tmp = (char*) malloc( l * sizeof( char ) );
drop the cast and add #include s<tdlib.h>. Also sizeof (char) is 1 by
definition
Also you'd need to check malloc's return value to detect failure.
// DO SOMETHING

free( tmp );

}

snippet 2:
void foo( int l )
{
char tmp[l];

// DO SOMETHING

}

What is the difference in advantage if I use snippet 1 or 2?
Snippet 2 requires far less typing and you can't accidently forget to call
free(), so it's less prone to memory leaks.

Bye, Jojo
 
B

Ben Pfaff

Kamui Shirow said:
snippet 1:
void foo( int l )
{
char* tmp;
tmp = (char*) malloc( l * sizeof( char ) );

sizeof(char) is always 1, so it's unnecessary to multiply by it.

I don't recommend casting the return value of malloc():

* The cast is not required in ANSI C.

* Casting its return value can mask a failure to #include
<stdlib.h>, which leads to undefined behavior.

* If you cast to the wrong type by accident, odd failures can
result.

In unusual circumstances it may make sense to cast the return value of
malloc(). P. J. Plauger, for example, has good reasons to want his
code to compile as both C and C++, and C++ requires the cast, as he
explained in article <[email protected]>.
However, Plauger's case is rare indeed. Most programmers should write
their code as either C or C++, not in the intersection of the two.

// DO SOMETHING

free( tmp );

}

snippet 2:
void foo( int l )
{
char tmp[l];

// DO SOMETHING

}

What is the difference in advantage if I use snippet 1 or 2?

Snippet 1 gives the code an opportunity to recover if the memory
for tmp cannot be allocated. In snippet 2, the program yields
undefined behavior and probably crashes if memory is unavailable.

Snippet 1 has the opportunity to extend the lifetime of the array
beyond the function's return. On the other hand, in snippet 2
the programmer can't forget to call free.

Many compilers do not yet implement the variable-length array
support from C99 that is required snippet 2 to compile.

I'd use the form of snippet 1 unless I knew that my code would
never be ported to a pre-C99 compiler. In practice, that means
that my code rarely if ever uses variable-length arrays.
 
R

Richard Heathfield

Kamui Shirow said:
Hello!

I will write a snippet to illustrate my doubt:

snippet 1:
void foo( int l )
{
char* tmp;
tmp = (char*) malloc( l * sizeof( char ) );

// DO SOMETHING

free( tmp );

}

Better:

#include <stdlib.h>

void foo(size_t n)
{
char *tmp = malloc(n * sizeof *tmp);
if(tmp != NULL)
{
/* do something */
free(tmp);
}
}
snippet 2:
void foo( int l )
{
char tmp[l];

// DO SOMETHING

}

What is the difference in advantage if I use snippet 1 or 2?

Snippet 1 doesn't require C99, and gives you control over failure.
 
W

Walter Roberson

Kamui Shirow said:
I will write a snippet to illustrate my doubt:
snippet 1:
void foo( int l )
{
char* tmp;
tmp = (char*) malloc( l * sizeof( char ) );
// DO SOMETHING
free( tmp );
}
snippet 2:
void foo( int l )
{
char tmp[l];
// DO SOMETHING
}
What is the difference in advantage if I use snippet 1 or 2?

Snippet 2 relies on Variable Length Arrays (VLA), which are part
of C99 but not part of C89. I have not used VLA myself, but reading
some of the other postings here, it sounds as if there are a noticable
number of compilers which either do not accept VLA at all or else
implement them differently than the C99 standard; in particular, I
believe people have said that gcc does something with VLA than
the C99 standard.

I have not looked at VLA, so I do not know what the largest
permitted array is.


Snippet 1 has a useless cast -- you do not need the (char *)
before the malloc(). That won't stop it from operating, that's
just not good style. Snippet 1 will work on C89 whereas Snippet 2 will
not work on C89. Snippet 1 has all the usual problems of malloc():
Depending on how the malloc() is implemented, malloc() can sometimes
be slow, or can sometimes not be able to find enough consequative
available memory even though there is enough available memory if you
could merge the seperate pieces of available memory together
("memory fragmentation"). And you've fallen into the classic pattern
in using malloc(), in that you failed to check to see whether
the system was able to give you the memory before you go ahead
and use it. Oh yes, and sizeof(char) is *defined* to be 1 so
there is no point in having the * sizeof(char) in the malloc().


Both snippets have the problem that you do not check that the variable l
is greater than 0 before you attempt to allocate space. Both would
fail for foo(-1).

You should also consider whether an "int" is large enough to
express the amount of space that might be desired. That's going
to depend on the context. It is legal in C implementations for
the largest int to be merely 32767 so if you were planning to
make foo available for a context in which someone might want
to allocate (say) 50000 bytes, then you should change the
user interface from specifying the size as an int . You could
change the size to long or (not in pure C89) long long, but
the most appropriate type for such a parameter is probably size_t .
 
J

Joachim Schmitz

Joachim Schmitz said:
Kamui Shirow said:
Hello!

I will write a snippet to illustrate my doubt:

snippet 1:
void foo( int l )
{
char* tmp;
tmp = (char*) malloc( l * sizeof( char ) );
drop the cast and add #include s<tdlib.h>. Also sizeof (char) is 1 by
definition
Also you'd need to check malloc's return value to detect failure.
// DO SOMETHING

free( tmp );

}

snippet 2:
void foo( int l )
{
char tmp[l];

// DO SOMETHING

}

What is the difference in advantage if I use snippet 1 or 2?
Snippet 2 requires far less typing and you can't accidently forget to call
free(), so it's less prone to memory leaks.
Outch, I've read the l for a 1...
So as others pointed out Snippet 2 would only work in C99 or other
C-Compilers with a non-standard extenion of VLAs

Bye, Jojo
 
M

Martin Ambuhl

Kamui said:
Hello!

I will write a snippet to illustrate my doubt:

snippet 1:
void foo( int l )
{
char* tmp;
tmp = (char*) malloc( l * sizeof( char ) );

1) It is always poor practice to cast the return value of malloc().
Remember to #include <stdlib.h> and remember to use a C compiler.
2) sizeof(char) is 1 by definition.

Your line above can be reduced to
tmp = malloc(i);

There remain two more issues.
3) it is possible that the type of tmp might change in future code.
That makes a better form
tmp = malloc(i * sizeof *tmp);
4) Always check the return value. If it is NULL, then malloc failed:
if (!tmp) {
/* handle error */
}
// DO SOMETHING
free( tmp );
}

snippet 2:
void foo( int l )
{
char tmp[l];

// DO SOMETHING

}

What is the difference in advantage if I use snippet 1 or 2?

5) Snippet 2 is not legal without a C99 compiler. Most compilers are
for C89 but not for C99. That is a huge difference.
6) Snippet 2 will allocate tmp in automatic storage. In almost all
implementations there is less room available for auto variables than for
dynamically allocated ones.
7) Snippet 2 does not allow you to check for the success or failure of
the attempt to declare the array tmp. A failure is almost certainly a
disaster.
 
D

Darko

Unbelievable how many people don't read other people's postings in the
same thread. In this thread, I think 90% of information is
unnecessarily repeated from the posting just above that one. C99, C99,
C99, C99, Don't cast, Don't cast, Don't cast, Don't cast, sizeof char
<=> 1, sizeof char <=> 1, sizeof char <=> 1, sizeof char <=> 1, sizeof
char <=> 1, .............
 
B

Ben Pfaff

Darko said:
Unbelievable how many people don't read other people's postings in the
same thread. In this thread, I think 90% of information is
unnecessarily repeated from the posting just above that one. C99, C99,
C99, C99, Don't cast, Don't cast, Don't cast, Don't cast, sizeof char
<=> 1, sizeof char <=> 1, sizeof char <=> 1, sizeof char <=> 1, sizeof
char <=> 1, .............

Usenet propagation isn't instantaneous. Quite often I'll read an
article, see no followups, reply, refresh the newsfeed, and
there'll already be a couple of other followups.
 
R

Richard Heathfield

Darko said:

C99, C99, Don't cast, Don't cast, Don't cast, Don't cast, sizeof char
<=> 1, sizeof char <=> 1, sizeof char <=> 1, sizeof char <=> 1, sizeof
char <=> 1, .............

And *still* people ignore the advice. Incredible, isn't it?
 
C

Christopher Benson-Manica

Darko said:
(I said, context restored:)
Unbelievable how many people don't read other people's postings in the
(snip)

My first inclination is to wonder exactly how your response follows
from mine (unless my newsreader incorrectly threaded your post), but
since you neglected to include any context in your post, it isn't
clear exactly what you were replying to.
 
W

Walter Roberson

Unbelievable how many people don't read other people's postings in the
same thread. In this thread, I think 90% of information is
unnecessarily repeated from the posting just above that one. C99, C99,
C99, C99, Don't cast, Don't cast, Don't cast, Don't cast, sizeof char
<=> 1, sizeof char <=> 1, sizeof char <=> 1, sizeof char <=> 1, sizeof
char <=> 1, .............

Timestamps from the first four replies, in CDT (Central Daylight Time):

13:42:20 13:45:13 13:54:29 13:54:33 (yes, only 4 seconds later.)

The latter of those was a longer response, written by me -- so it
was in preparation starting even before that first timestamp, 13:42:20 .

After the initial burst of responses, there was another several hours
later, something like 21:12; it did repeat a couple of points,
but also made a couple of new points.
 
C

Chris Dollin

Darko said:
Unbelievable how many people don't read other people's postings in the
same thread. In this thread, I think 90% of information is
unnecessarily repeated from the posting just above that one. C99, C99,
C99, C99, Don't cast, Don't cast, Don't cast, Don't cast, sizeof char
<=> 1, sizeof char <=> 1, sizeof char <=> 1, sizeof char <=> 1, sizeof
char <=> 1, .............

The price of no duplicate answers is no answers at all.

--
"Go not to the Drazi for counsel, Unsaid /Babylon 5/
for they will answer both 'green' and 'purple'."

Hewlett-Packard Limited registered no:
registered office: Cain Road, Bracknell, Berks RG12 1HN 690597 England
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top