free(); after return();?

R

richard

True, but in this case the absence of parentheses is a marker of
a good understanding of what's going on -- namely that "sizeof"
is not a function, and does not require parentheses if its
operand is an object (rather than a type). Compare

double *x;

/* below: not recommended, but the parentheses are needed */
x = malloc(10 * sizeof(double));

/* recommended, and parentheses would be redundant */
x = malloc(10 * sizeof *x);

For me, 10 * sizeof *x
appears on quick glance as if we're multiplying 3 things, while the parens more
clearly associate sizeof and *x. (quickly glancing is, of course, never a good
way of parsing code)

In any event, thanks to most of you for explaining why you prefer sizeof object
and sizeof(type) rather than sizeof(object) and sizeof(type).
 
I

Irrwahn Grausewitz

Peter Nilsson said:
...

What of it?

There's only one between the operator and the paranthesized expression.
Some people's style is to code with spaces between the function name and the
parenthesised argument list. It's not my preference, but there's nothing
syntactically wrong with it.

Nobody said so.
 
P

Peter Nilsson

Irrwahn Grausewitz said:
There's only one between the operator and the paranthesized expression.

Umm... why is that important?

Two spaces would look stupid I grant you.
Nobody said so.

AFAIK, no one said sizeof was a function either, so I wasn't sure why you
mentioned it. Seeing your two statements together, separated by a colon, I
thought your first comment was somehow meant to imply the second.

Are you simply saying that sizeof should always be followed by a space in
light of its status as an operator? If so, you wouldn't be the only one, but
I don't see it as being particularly crucial to writing readable or robust
code [in the circumstance where the operand is a type or parethesised
expression]. YMMV.
 
B

Ben Pfaff

ipo said:
1. malloc() returns a void pointer and there is absolutely nothing wrong
with using a type cast on the return value. In case you did not know,
stdlib.h has nothing to do with casting. Whether you decide to cast or not
any decent compiler will generate a warning and assume a return value of int
for malloc() if stdlib.h is not included.

2. By definition sizeof(char) maybe 1 in your machine. Not mine. So make
sure to use sizeof(char) to be portable.

Finally, whoever told you that void main(void) is not valid C? I recommend
you get a copy of K&R and read it.

\|||/
(o o)
|~~~~ooO~~(_)~~~~~~~|
| Please |
| don't feed the |
| TROLLS ! |
'~~~~~~~~~~~~~~Ooo~~'
|__|__|
|| ||
ooO Ooo
 
I

ipo

Richard Heathfield said:
Wrong. There is plenty wrong with it. All code should either do something
good or stop something bad happening. A malloc cast does neither. What it
/can/ do, however, is prevent you from being told that something bad has
happened. Therefore, it confers no advantage and yet suffers from a
possible disadvantage. Therefore, there is no good reason to include it.


If my memory does not fail me, prior to the ANSI C days, malloc() was
declared as char *malloc(). Having said this, please refer to K&R[78]
p.133-134 where the authors use char *alloc(). For additional comments and
examples please refer to the following:

1. The C++ Programming language. Bjarne Stroustrup, p.52-53
2. Checking C Programs with lint. Ian Darwin, p.8-9
3. MDSN documentation on malloc()
Jack knows that full well. Your inability to understand his point does not
constitute a failure of understanding on his part.

I understood his point very well but please let me remind you that he
started the flames...
Wrong. If the cast is omitted without <stdlib.h> being included, the
compiler /must/ diagnose. If the cast is included, the diagnostic becomes
optional.

If the cast is omitted and <stdlib.h> is not included the compiler: 1) will
assume that malloc() returns int, 2) provide you with a warning to that
effect, and 3) warn you about mixing char * and int. If the cast is
Wrong. The ISO C standard requires sizeof(char) to evaluate to 1 in all
cases.

I'll grant you this one.
Whoever told you it was?

How about Section 5.1.2.2.1.1 of the ISO C Standard (ISO/IEC 9899:1999)? See
http://homepages.tesco.net/~J.deBoynePollard/FGA/legality-of-void-main.html
Feel free to provide a page reference to a void main(void) program in K&R.
You won't find one, but the read might do you some good.

It's true I will not but that does not imply that the construct is not
perfectly legal.
 
J

Joona I Palaste

If my memory does not fail me, prior to the ANSI C days, malloc() was
declared as char *malloc(). Having said this, please refer to K&R[78]
p.133-134 where the authors use char *alloc(). For additional comments and
examples please refer to the following:
1. The C++ Programming language. Bjarne Stroustrup, p.52-53
2. Checking C Programs with lint. Ian Darwin, p.8-9
3. MDSN documentation on malloc()

So? First of all, we don't live in days prior to ANSI C any more.
Second of all, neither Stroustrup, Darwin, or MS have any authority
over C.
How about Section 5.1.2.2.1.1 of the ISO C Standard (ISO/IEC 9899:1999)? See
http://homepages.tesco.net/~J.deBoynePollard/FGA/legality-of-void-main.html

I take it that web page reads the C standard like the Devil reads the
Bible. I.e. trying to pick faults wherever it can.

--
/-- Joona Palaste ([email protected]) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"Holy Banana of this, Sacred Coconut of that, Magic Axolotl of the other."
- Guardian in "Jinxter"
 
R

Richard Heathfield

ipo said:
If my memory does not fail me, prior to the ANSI C days, malloc() was
declared as char *malloc().

Correct. That was around 15 years ago. If you wish to discuss K&R C rather
than ISO C, you should state that explicitly to avoid confusion.
Having said this, please refer to K&R[78]
p.133-134 where the authors use char *alloc(). For additional comments and
examples please refer to the following:

1. The C++ Programming language. Bjarne Stroustrup, p.52-53
Off-topic.

2. Checking C Programs with lint. Ian Darwin, p.8-9
Irrelevant.

3. MDSN documentation on malloc()
Irrelevant.
Jack knows that full well. Your inability to understand his point does
not constitute a failure of understanding on his part.

I understood his point very well but please let me remind you that he
started the flames...

You are confusing flaming with critical analysis.
If the cast is omitted and <stdlib.h> is not included the compiler: 1)
will assume that malloc() returns int, 2) provide you with a warning to
that effect, and 3) warn you about mixing char * and int.

Right, and that's why it's important to omit the cast.

If the cast is
specified and <stdlib.h> is not included the compiler, if not lint, will
still warn you about the return type of malloc().

It is not required to issue a diagnostic in that circumstance.

How about Section 5.1.2.2.1.1 of the ISO C Standard (ISO/IEC 9899:1999)?

That section makes it perfectly clear that any return type other than int
invokes undefined behaviour on any implementation that does not
specifically document some other interface. Thus, void main(void) cannot be
used in code that is intended to be portable.

http://homepages.tesco.net/~J.deBoynePollard/FGA/legality-of-void-main.html

Irrelevant. The Standard defines C.
It's true I will not but that does not imply that the construct is not
perfectly legal.

No, it doesn't, but that's irrelevant too. The Standard explicitly says that
main returns int. If you define it to return void, you are at the mercy of
your implementation.
 
S

Sheldon Simms

I take it that web page reads the C standard like the Devil reads the
Bible. I.e. trying to pick faults wherever it can.

No, it simply says that it is permissable to define main in some
implementation-defined manner. (i.e. - with a return type of void, as
long as that is explicitly allowed by the implementation).

That is correct, but that only means that void main(void) is valid
in reference to some implementation of C that explicitly allows it.

It doesn't mean anything for implementation-independent validity of
void main(void) independent of implementation.

ipo's argument is approximately the same as saying that

int main (void)
{
_Frubnax w = 0;
return w;
}

is valid C, since "an implementation is allowed to define new keywords
that provide alternative ways to designate a basic (or any other) type"
(6.2.5.14)
 
P

pete

ipo said:
a copy of K&R

If you don't have the errata, then you don't have K&R.

http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html

142(§6.5, toward the end):
The remark about casting the return value of malloc
("the proper method is to declare
.... then explicitly coerce") needs to be rewritten.
The example is correct and works,
but the advice is debatable in the context of the
1988-1989 ANSI/ISO standards. It's not necessary
(given that coercion of void * to ALMOSTANYTYPE * is automatic),
and possibly harmful if malloc, or a proxy for it,
fails to be declared as returning void *.
The explicit cast can cover up an unintended error.
On the other hand, pre-ANSI, the cast was necessary, and it is in C++
also.
 
E

E. Robert Tisdale

Jack said:
NEVER cast the pointer returned by malloc() in C.
It is not necessary if <stdlib.h> has been included
and can hide a valuable warning if <stdlib.h> has not been included.

That's *not* the best advice
if you need to compile your code with a C++ compiler:
> cat malloc.c
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char* argv[]) {
const
int n = 20;
int* p = malloc(n*sizeof *p);
for (int j = 0; j < n; ++j)
p[j] = j;
for (int j = 0; j < n; ++j)
fprintf(stdout, "%2d = p[%2d]\n", p[j], j);
return 0;
}
> g++ -Wall -ansi -pedantic -x C++ -o malloc malloc.c
malloc.c: In function `int main(int, char**)':
malloc.c:7: warning: invalid conversion from `void*' to `int*'
> ./malloc
0 = p[ 0]
1 = p[ 1]
.
.
.
19 = p[19]
 
P

pete

ipo wrote:
Finally, whoever told you that void main(void) is not valid C?
I recommend you get a copy of K&R and read it

What page is void main(void) on ?

N869
5.1.2.2.1 Program startup
[#1] The function called at program startup is named main.
The implementation declares no prototype for this function.
It shall be defined with a return type of int and with no
parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv,
though any names may be used, as they are local to the
function in which they are declared):
int main(int argc, char *argv[]) { /* ... */ }
or equivalent; or in some other implementation-defined
manner.

So, void main(void), would be an implementation defined manor.
You said something about sizeof(char),
which indicated that you value portability.
int main(void) is portable, void main(void) isn't.
This newsgroup focuses on portable code,
to the extent that code with void main(void), is Off Topic.
 
R

Richard Heathfield

E. Robert Tisdale said:
That's *not* the best advice

Yes, it is. I don't seek to persuade Mr Tisdale of this fact, of course.
This reply is merely for the record.
if you need to compile your code with a C++ compiler:

....then write C++ code. This, however, is comp.lang.c, where we discuss C
code, not C++ code. There is a significant difference between C code and
C++ code. That is, C programs generally do not compile under a C++
compiler, and C++ programs generally do not compile under a C compiler.

It is possible to construct programs which compile under both a C compiler
and a C++ compiler, but then it is possible to construct programs which
compile as C, BASIC, and Perl. This is an interesting diversion, but not
appropriate for production code.

In general, use a C compiler for C code, and a C++ compiler for C++ code.
Mixing the two is a recipe for disaster.


If you want C++, you know where to find it.
 
L

LibraryUser

E. Robert Tisdale said:
That's *not* the best advice
if you need to compile your code with a C++ compiler:

Primus: Closely examine the group name. I fail to see any ++
therein. Intelligent people compile C code with a C compiler.

Secundus: That IS the best advice.

Tertius: If ERT would refrain from posting misinformation, we
could reduce traffic here since the corrections, for the benefit
of the newbies, would no longer be necessary. "Ignore anything
from ERT" is generally good advice.
 
J

Jack Klein

FYI:

1. malloc() returns a void pointer and there is absolutely nothing wrong
with using a type cast on the return value. In case you did not know,
stdlib.h has nothing to do with casting. Whether you decide to cast or not
any decent compiler will generate a warning and assume a return value of int

Every character that a programmer types into a source code file
increases the possibility for a code defect. Redundant casts are
particularly high on that list.

As for your second assertion, a diagnostic is required if you assign
the return value of an unprototyped function to any type of pointer.
No such diagnostic is required in the presence of a cast.

As for "decent", I have seen many compilers that can be configured to
output a diagnostic message for a call to any function without a
prototype in scope. Sadly, many programmers do not configure their
compilers to operate that way. But I have never seen any compiler
that issues a specific warning for this particular scenario, and at
least a few of the compilers I have used over the decades are
"decent".
for malloc() if stdlib.h is not included.

2. By definition sizeof(char) maybe 1 in your machine. Not mine. So make
sure to use sizeof(char) to be portable.

Then you are posting in the wrong newsgroup, because you are not using
a C compiler. I use compilers for architectures where CHAR_BIT is 16,
and others where CHAR_BIT is 32. In both cases sizeof(char) is 1, by
definition, and it always will be.
Finally, whoever told you that void main(void) is not valid C? I recommend
you get a copy of K&R and read it.
ipo

I have copies of K&R, both the first and second editions. In fact the
rare first printing of the second edition. My original K&R no longer
qualifies for the once-common nickname "the white book", as 25 years
have added a distinctly yellowish color to its pages.

However, in those 25 years, I might have missed something. Can you
provide a quotation from any edition of K&R where they state that
"void main()" is corrects? I thought not.

And you're still top posting, which is still ill-mannered.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
 
J

Jack Klein

That's *not* the best advice
if you need to compile your code with a C++ compiler:

There is actually nothing at all wrong with writing C code to compile
as C++. One of Bjarne Stroustrup's original purposes in the
development was to create a "better C", and from some points of view
he succeeded quite well.

Nevertheless, C code that compiles with a C++ compiler and produces an
executable with identical results limits one to a subset of C (not
just a subset of C++), and a much smaller one than most people
realize.

The biggest problem with your mention of "if you need to compiler your
code with a C++ compiler" is that it is just plain off-topic here.
Just as much off-topic as discussing attempts to write C code to
compile with a FORTRAN or Lisp compiler.

As far as this newsgroup and the C language are concerned, the
existence of the C++ programming language has been recognized since
October 1999 in the current C standard by references in four foot
notes, and foot notes are not normative:

"182) C++ implementations should define these macros only when
__STDC_FORMAT_MACROS is defined before <inttypes.h> is included."

"217) C++ implementations should define these macros only when
__STDC_LIMIT_MACROS is defined before <stdint.h> is included."

"218) C++ implementations should define these macros only when
__STDC_LIMIT_MACROS is defined before <stdint.h> is included."

"220) C++ implementations should define these macros only when
__STDC_CONSTANT_MACROS is defined before <stdint.h> is included."

Sadly, the topic of writing code that executes with the same results
when compiled with both C and C++ compilers if not particularly
welcome in C++ groups either, as there will likely be many responses
along the lines of "use this or that C++ feature instead."

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
 
J

Joona I Palaste

There is actually nothing at all wrong with writing C code to compile
as C++. One of Bjarne Stroustrup's original purposes in the
development was to create a "better C", and from some points of view
he succeeded quite well.
Nevertheless, C code that compiles with a C++ compiler and produces an
executable with identical results limits one to a subset of C (not
just a subset of C++), and a much smaller one than most people
realize.
The biggest problem with your mention of "if you need to compiler your
code with a C++ compiler" is that it is just plain off-topic here.
Just as much off-topic as discussing attempts to write C code to
compile with a FORTRAN or Lisp compiler.
As far as this newsgroup and the C language are concerned, the
existence of the C++ programming language has been recognized since
October 1999 in the current C standard by references in four foot
notes, and foot notes are not normative:
"182) C++ implementations should define these macros only when
__STDC_FORMAT_MACROS is defined before <inttypes.h> is included."
"217) C++ implementations should define these macros only when
__STDC_LIMIT_MACROS is defined before <stdint.h> is included."
"218) C++ implementations should define these macros only when
__STDC_LIMIT_MACROS is defined before <stdint.h> is included."
"220) C++ implementations should define these macros only when
__STDC_CONSTANT_MACROS is defined before <stdint.h> is included."
Sadly, the topic of writing code that executes with the same results
when compiled with both C and C++ compilers if not particularly
welcome in C++ groups either, as there will likely be many responses
along the lines of "use this or that C++ feature instead."

The problem I see with ERT's remark, and remarks of that kind, is that
they require clairvoyance. Suppose some day someone develops a "sort-of"
superset of C++, or another "sort-of" superset of C? Should we already
begin to write C programs (or C++ programs) that would work correctly
in that?

--
/-- Joona Palaste ([email protected]) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"Make money fast! Don't feed it!"
- Anon
 
I

ipo

Jack Klein said:
int

Every character that a programmer types into a source code file
increases the possibility for a code defect. Redundant casts are
particularly high on that list.

I do agree with your comments but I also think that some assumptions were
made in your replies as well as mine. I also happen to own a first printing
of K&R78 and if you turn to page 133 you will see that the authors make use
of an explicit cast on the pointer returned by the alloc() function that
they introduce elsewhere in the text. As my replies were addressing the
practice in the context of K&R78, I hope that this will serve to clarify any
difference of opinion..
As for your second assertion, a diagnostic is required if you assign
the return value of an unprototyped function to any type of pointer.
No such diagnostic is required in the presence of a cast.

As for "decent", I have seen many compilers that can be configured to
output a diagnostic message for a call to any function without a
prototype in scope. Sadly, many programmers do not configure their
compilers to operate that way. But I have never seen any compiler
that issues a specific warning for this particular scenario, and at
least a few of the compilers I have used over the decades are
"decent".


Then you are posting in the wrong newsgroup, because you are not using
a C compiler. I use compilers for architectures where CHAR_BIT is 16,
and others where CHAR_BIT is 32. In both cases sizeof(char) is 1, by
definition, and it always will be.

You're absolutely right. Please refer to my previous posting where I
admitted my error.
I have copies of K&R, both the first and second editions. In fact the
rare first printing of the second edition. My original K&R no longer
qualifies for the once-common nickname "the white book", as 25 years
have added a distinctly yellowish color to its pages.

However, in those 25 years, I might have missed something. Can you
provide a quotation from any edition of K&R where they state that
"void main()" is corrects? I thought not.

It is also true that I will not be able to provide you with an example from
either text. If my memory serves me right, the type specifier void was not
even part of the specification that was in place at the time of the first
printing. However, note that Section 5.1.2.2.1.1 of the ISO C Standard
(ISO/IEC 9899:1999) does allow for the definition of void main(), even if at
the price of portability.
And you're still top posting, which is still ill-mannered.

I welcome your criticisms as well as everybody else's but just as you find
my top posting ill-mannered so I find people raising their voice. When
criticized constructively I will be the first to acknowledge his mistakes.

ipo
 
R

Richard Heathfield

ipo said:
I do agree with your comments but I also think that some assumptions were
made in your replies as well as mine. I also happen to own a first
printing of K&R78 and if you turn to page 133 you will see that the
authors make use of an explicit cast on the pointer returned by the
alloc() function that they introduce elsewhere in the text. As my replies
were addressing the practice in the context of K&R78, I hope that this
will serve to clarify any difference of opinion..

Pre-ANSI, the cast was required. Nobody disputes that. ANSI C was published
15 years ago, and there was widespread take-up of the Standard in
widely-available compilers. There is little, if any, justification for
using a cast nowadays. If your compiler vendor doesn't support the ANSI C
standard of 1989 by now, perhaps it's time to start complaining.

It is also true that I will not be able to provide you with an example
from either text. If my memory serves me right, the type specifier void
was not even part of the specification that was in place at the time of
the first printing. However, note that Section 5.1.2.2.1.1 of the ISO C
Standard (ISO/IEC 9899:1999) does allow for the definition of void main(),
even if at the price of portability.

It also allows for the definition of double main(), char *main(), and struct
{ float (*fp)(char *, float, double); int i; } main(), but I don't see you
advocating those anywhere. Why not? Could it be because they're not
portable? Well, neither is void main(). Your position is inconsistent.

I welcome your criticisms as well as everybody else's but just as you find
my top posting ill-mannered so I find people raising their voice. When
criticized constructively I will be the first to acknowledge his mistakes.

You /have/ been criticised constructively, and have been /slow/ to
acknowledge your mistakes.
 
I

ipo

Richard Heathfield said:
Pre-ANSI, the cast was required. Nobody disputes that. ANSI C was published
15 years ago, and there was widespread take-up of the Standard in
widely-available compilers. There is little, if any, justification for
using a cast nowadays. If your compiler vendor doesn't support the ANSI C
standard of 1989 by now, perhaps it's time to start complaining.

I do not necessarily agree with your views on the use of casts. There are
millions of lines of C code lying around that date back to the early days
that still need to be maintained. In more than one occassion I've seen
entire rooms with hundreds of volumes of source code printouts that had no
documentation whatsoever because it got lost the last time the company
moved. Faced with that the last thing that would cross my mind would be to
upgrade compilers.
It also allows for the definition of double main(), char *main(), and struct
{ float (*fp)(char *, float, double); int i; } main(), but I don't see you
advocating those anywhere. Why not? Could it be because they're not
portable? Well, neither is void main(). Your position is inconsistent.

I do not advocate those because they're not as widespread as void main(). As
I'm sure you already know there are countless of texts that use the
construct, starting with the Xlib Programming Manual. And I do not think I
need to remind you of the number of Windows-based compilers by major
manufacturers that support it which, like it or not, influence the majority
of developers.
 

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

Forum statistics

Threads
474,079
Messages
2,570,574
Members
47,206
Latest member
Zenden

Latest Threads

Top