C99 Question

  • Thread starter Vijay Kumar R Zanvar
  • Start date
R

Richard Heathfield

Alexander said:
begin followup to Richard Bos:

Let's see if I understand this right.
The danger is that the diagnostic

initialization makes pointer from integer without a cast

is mandatory for a conforming compiler, while

implicit declaration of function `malloc'

is not.

Not in C99 (which is the scenario under consideration), because implicit
function declarations were removed in C99.

I think Richard Bos is making a valid *philosophical* point. The cast
remains inadvisable, even though in C99 it will no longer mask the omission
of <stdlib.h>. I agree with him that the cast is inadvisable, but I'd
hesitate to use the word "dangerous" in a C99 context.
 
C

CBFalconer

E. Robert Tisdale said:
Good question! The ANSI/ISO C 99 standard does *not* say that
the return value of malloc should not be casted.

I *always* cast malloc's return value

Mr Zanvar should note that ERT, better known in these parts as
Trollsdale, is usually wrong and gives (as in this case) bad
advice.
 
C

Clark Cox

"E. Robert Tisdale said:
Good question! The ANSI/ISO C 99 standard does *not* say that the
return value of malloc should not be casted.

I *always* cast malloc's return value

char* p = (char*)malloc(n*sizeof(char));

so that my C++ compiler won't complain.

Pick a language. Either write C or write C++. If you're writing C++,
then use new (and don't cast), if you're writing C, then use malloc (and
don't cast). If, you are writing C, but trying to feed it to a C++
compiler, then why not just write C++, and be through with it?
There is *no* advantage to omitting the cast.

That is simply wrong. If, for instance, you forget to include stdlib.h,
and malloc's prototype is not in scope, a (C89) compiler will assume
that malloc is defined as "int malloc()", which means that the result is
undefined, and you should get some diagnostic from your compiler. Now,
on platforms where sizeof(int) == sizeof(void*), and pointers and
integers are returned in the same way, this *might* be fine, but you
can't count on it.
It is purely a style issue but some C programmers have become fond of
this style and invented various *lame* arguments to justify their
personal aesthetics.

Casting, in this case, does nothing but hide potential errors.
 
J

Jack Klein

Beg to differ. It _is_ dangerous. Not to the code, but to the
programmer, and even more importantly to the maintainer.

Richard

The reason that it is not as dangerous in a conforming C99
implementation is that C99 requires a declaration in scope when a
function is called. It is still dangerous if the declaration is not a
prototype, as one could insert the following in one's source file to
shut up the compiler:

void *malloc();

....which is a declaration but not a prototype, causing the compiler to
pass the argument as a signed type, rather than a size_t.

--
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

Not in C99 (which is the scenario under consideration), because implicit
function declarations were removed in C99.

I think Richard Bos is making a valid *philosophical* point. The cast
remains inadvisable, even though in C99 it will no longer mask the omission
of <stdlib.h>. I agree with him that the cast is inadvisable, but I'd
hesitate to use the word "dangerous" in a C99 context.

Undefined behavior under C99:

void *malloc(); /* an acceptable declaration */

void my_function(void)
{
char *fred = malloc(100);
}

....because the declaration is not a full prototype and the argument
will be passed as a signed int instead of a size_t.

Not too swift to toss in one's own declaration? Agreed. But doing so
to silence the compiler diagnostic is not much different than tossing
in the cast to do the same thing.

Probably depends on which diagnostic a particular C99 implementation
would output for the code without the declaration (missing declaration
or int-to-pointer conversion), or which would be first if it emitted
both.

--
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
 
C

CBFalconer

P.J. Plauger said:
Whatever his record, I happen to agree with him on this matter.

However you have, I believe, a different motive. You want your
shrouded source to be compilable by unwashed idiots on any
compiler without complaint or handholding.
 
B

Ben Pfaff

CBFalconer said:
And it also encourages you to treat the presence of ANY cast as an
indication of a potential problem. There are very few places they
are really necessary, with calls to variadic functions heading my
list.

There are several situations where a cast legitimately comes in handy:

* Conversion of one type's range to another's, as in the
argument to the <ctype.h> to*() and is*() functions:
isupper((unsigned char) c)

* Conversion of an integer to a floating-point type for
use in arithmetic. (Sure, you can assign it to a
variable or multiply it by 1.0, but a cast can
sometimes clarify what you're doing.)

* Converting a pointer to the first member of a structure
to a pointer to the structure, or a pointer to a member
of a union to a pointer to the union.

* Converting an lvalue to an rvalue for use in macros
that can be used for access to objects but should not
be used to modify those objects. (The unary plus
operator is an alternative.)

* Casting between different pointer-to-character types
for, e.g., passing a unsigned char array to strcpy().
(You can avoid it by using a void * pointer variable as
an intermediary, but that's hardly an improvement.)

* Silencing compiler warnings about `comparing signed and
unsigned types' ;-(

* Passing a null pointer to a varargs function.
 
K

Keith Thompson

E. Robert Tisdale said:
Good question! The ANSI/ISO C 99 standard does *not* say that
the return value of malloc should not be casted.

I *always* cast malloc's return value

char* p = (char*)malloc(n*sizeof(char));

so that my C++ compiler won't complain.

The best way to keep your C++ compiler from complaining is to avoid
feeding it C code.
There is *no* advantage to omitting the cast.
It is purely a style issue
but some C programmers have become fond of this style
and invented various *lame* arguments
to justify their personal aesthetics.

Nonsense, as usual.
 
K

Keith Thompson

P.J. Plauger said:
You make me feel young again.

I think you've answered this before, but I don't remember the details,
I'm too lazy to do a search, and it probably couldn't hurt to repeat
it here.

Why do you want to compile C code with a C++ compiler?
 
P

P.J. Plauger

I think you've answered this before, but I don't remember the details,
I'm too lazy to do a search, and it probably couldn't hurt to repeat
it here.

I'm almost too lazy to answer, but since it's New Year's Eve and
I'm having trouble starting another project...
Why do you want to compile C code with a C++ compiler?

Actually, I want to compile our C code with *all* significant C and C++
compilers.

For one thing, the C++ Standard is intentionally silent (thanks to me)
on whether the C library has "C" or "C++" linkage. We have some OEM
customers who want the C names mangled, to provide link-time argument
type checking, and we have many others who want C names to look like,
well, C names.

For another thing, C++ is indeed in some ways a "better C", as
Stroustrup has been asserting for the past decade and a half. We
find bugs in hoary C code quite often when compiling it as C. So
it's just part of our shop discipline to make sure all our C code
compiles as C++ too.

I agree that you have to write more casts in C++ than in C, and
I agree that casts can sometimes disguise other problems. But it's
been my experience over the past ten years that casts tend to hide
stupid bugs, which are relatively easy to find, while compiling as
C++ tends to find subtler bugs, which are not. The tradeoff has
been well worth it for us.

HTH,

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
 
A

Alexander Bartolich

begin followup to Keith Thompson:
Why do you want to compile C code with a C++ compiler?

The obvious recursive answer: To catch the problem of missing

#include <stdlib.h>

even if the return value of every malloc is casted...

Seriously, the subset of C that also compiles as C++ is a nice,
simple language. A and C++ compiler will emit a clear error where
naked C will just warn about seemingly obscure stuff.

$ cat a.c
int main() {
int print_a_double(int);
return print_a_double(1);
}

$ cat b.c
#include <stdio.h>
void print_a_double(double x) { printf("%g\n", x); }

$ gcc -Wall a.c b.c && ./a.out
5.04822

Oops. Evil. Incarnate.

$ g++ a.c b.c
/tmp/ccvpYiSi.o(.text+0x16): In function `main':
: undefined reference to `print_a_double(int)'
collect2: ld returned 1 exit status

So even on outright misleading prototype is caught by C++,
though only in the linking phase. The more realistic case of

extern print_a_double();

instead of

int print_a_double(int);

won't even compile with C++.
 
E

E. Robert Tisdale

Richard said:
C and C++ are different languages.

In C++, you'd be better off doing this:

char *p = new char[n];

unless you wanted to resize the string at some point
in which case you'd be better off using a std::string.
> cat richard.c
#include <stdio.h>

int richard(size_t n) {
char *p = new char[n];
return n;
}
> gcc -Wall -std=c99 -pedantic -c richard.c
richard.c: In function `richard':
richard.c:4: `new' undeclared (first use in this function)
richard.c:4: (Each undeclared identifier is reported only once
richard.c:4: for each function it appears in.)
richard.c:4: parse error before "char"
richard.c:4: warning: unused variable `p'


The problem is that I can't get my C compiler to accept this.

Are you suggesting that
I should write and maintain two separate versions of function richard?
Just so that I can use one with C and the other with C++ programs?
Do you do that?
And, if so, does your employer/client know that you do that?

I think that most (at least my) employers/clients would prefer that
I would develop and maintain for a single version
which both C and C++ compilers could compile.
 
K

Kevin Goodsell

E. Robert Tisdale said:
Richard said:
C and C++ are different languages.

In C++, you'd be better off doing this:

char *p = new char[n];

unless you wanted to resize the string at some point
in which case you'd be better off using a std::string.

cat richard.c
#include <stdio.h>

int richard(size_t n) {
char *p = new char[n];
return n;
}
gcc -Wall -std=c99 -pedantic -c richard.c
richard.c: In function `richard':
richard.c:4: `new' undeclared (first use in this function)
richard.c:4: (Each undeclared identifier is reported only once
richard.c:4: for each function it appears in.)
richard.c:4: parse error before "char"
richard.c:4: warning: unused variable `p'


The problem is that I can't get my C compiler to accept this.

Are you suggesting that
I should write and maintain two separate versions of function richard?
Just so that I can use one with C and the other with C++ programs?
Do you do that?
And, if so, does your employer/client know that you do that?

I think that most (at least my) employers/clients would prefer that
I would develop and maintain for a single version
which both C and C++ compilers could compile.

Why stop there? Why not make it valid Pascal, Perl, Java, Basic, and
Lisp also? Does your employer know that your code will have to be
completely rewritten when they decide they want to compile it as a Java
program?

Sometimes I write C and sometimes I write C++. I even write some
libraries that are usable in both. It's stupid, in my opinion to write
in the common subset of C and C++ without a very good reason. Plauger
seems to have a good reason to do so. Most people don't. Do you?

-Kevin
 
E

E. Robert Tisdale

Kevin said:
Sometimes I write C and sometimes I write C++.
I even write some libraries that are usable in both.

Do *you* have good reasons for doing so?
It's stupid, in my opinion to write in the common subset of C and C++
without a very good reason.
Plauger seems to have a good reason to do so.
Most people don't.

How could you know that?

My reasons are the same as Plauger's.
 
R

Richard Heathfield

E. Robert Tisdale said:
Richard said:
C and C++ are different languages.

In C++, you'd be better off doing this:

char *p = new char[n];
The problem is that I can't get my C compiler to accept this.

I imagine your Pascal compiler has trouble with the malloc call you showed
us, too. So what?
Are you suggesting that
I should write and maintain two separate versions of function richard?

Not at all.
Just so that I can use one with C and the other with C++ programs?
Do you do that?

No, I'm suggesting that, if you wish to use C code in a C++ program, you can
generally do it without recompiling the C code.
And, if so, does your employer/client know that you do that?

I think that most (at least my) employers/clients would prefer that
I would develop and maintain for a single version
which both C and C++ compilers could compile.

Presumably they would also prefer for your single version to compile under
Pascal, Fortran, and COBOL too. Does it?
 

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,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top