Thought I knew what I was doing
Author Message
Thought I knew what I was doing

Hi there

I have a function:            double f(double x, double y);

And I have a struct:          struct control {
double k[4];
double *y;
}

where:                        struct control ctl;
ctl.y = (double *)malloc(GRID*sizeof(double));

Lastly, I have a question.

Is ctl.y[x]  (where x=4, say) a double or is it a pointer to double?
how about *ctl.y[x]?   i tried f(x, ctl.y[x]) and f(x, *ctl.y[x]) and
f(x, *(ctl.y[x])) but my compiler doesn't like any of them.

What is the proper way to get the value of ctl.y[x] to my function?

pete

Thu, 19 Oct 2000 03:00:00 GMT
Thought I knew what I was doing

: Hi there

: I have a function:            double f(double x, double y);

: And I have a struct:          struct control {
:                                  double k[4];
:                                  double *y;
:                               }

: where:                        struct control ctl;
:                               ctl.y = (double *)malloc(GRID*sizeof(double));

: Lastly, I have a question.

: Is ctl.y[x]  (where x=4, say) a double or is it a pointer to double?

A double - assuming that x < GRID.  The two operators are the same
precedence and associate left.

: how about *ctl.y[x]?   i tried f(x, ctl.y[x]) and f(x, *ctl.y[x]) and
: f(x, *(ctl.y[x])) but my compiler doesn't like any of them.

I don't know what *ctl.y[x] might be, but you're trying to dereference
a floating point value, and nothing good can come of that.

: What is the proper way to get the value of ctl.y[x] to my function?

Well, you can't use a double value as an array index; you'll need
to convert x somehow.  What error messages does the compiler give?

Will

Thu, 19 Oct 2000 03:00:00 GMT
Thought I knew what I was doing

Quote:
>Hi there

>I have a function:            double f(double x, double y);

>And I have a struct:          struct control {
>                                 double k[4];
>                                 double *y;
>                              }

>where:                        struct control ctl;
>                              ctl.y = (double *)malloc(GRID*sizeof(double));

Don't forget to test the result of malloc() for failure and to
#include <stdlib.h> for an appropriate prototype. The case is not required
in C and can hide (but not fix) errors such as failure to include <stdlib.h>.

Quote:
>Lastly, I have a question.

>Is ctl.y[x]  (where x=4, say) a double or is it a pointer to double?

ctl.y is a pointer to double so ctl.y[x] is a double (just as if ptr is
a pointer to char then ptr[x] is a char). Note that the only valid values
of x here are between 0 and GRID-1 inclusive.

Quote:

Invalid - you can't apply the unary * operator to a double operand.

&ctl.y[x]

is valid and produces the address of ctl.y[x] with type pointer to double.

i tried f(x, ctl.y[x]) and f(x, *ctl.y[x]) and

Quote:
>f(x, *(ctl.y[x])) but my compiler doesn't like any of them.

If you got an error message always state what it was. I don't see anything
specifically wrong here, as long as x has integer type. With something
like this it is always best to post a minimal, but complete program. If you
don't it's Sod's Law that the problem will be in a part of the code
you didn't post. Posting a compilable program also allows others to check
and work on your code with their compilers.

--
-----------------------------------------

-----------------------------------------

Thu, 19 Oct 2000 03:00:00 GMT
Thought I knew what I was doing

Quote:

> Hi there

> I have a function:            double f(double x, double y);

> And I have a struct:          struct control {
>                                  double k[4];
>                                  double *y;
>                               }

> where:                        struct control ctl;
>                               ctl.y = (double *)malloc(GRID*sizeof(double));

> Lastly, I have a question.

> Is ctl.y[x]  (where x=4, say) a double or is it a pointer to double?

ctl.y[x] is of type double if x is of type int, else it is an error.

Quote:

This one is incorrect since ctl.y[x] is not a pointer.

i tried f(x, ctl.y[x])

This one is the correct way of calling. Your compiler may complain
because you might have defined 'x' as a double instead of an int. Array
subscripts can only be integers.

and f(x, *ctl.y[x]) and

Quote:
> f(x, *(ctl.y[x])) but my compiler doesn't like any of them.

These statements are definitely incorrect.

K. Rajesh

Sat, 21 Oct 2000 03:00:00 GMT
Thought I knew what I was doing

says...

Quote:

> Don't forget to test the result of malloc() for failure and to
> #include <stdlib.h> for an appropriate prototype. The case is not required
> in C and can hide (but not fix) errors such as failure to include <stdlib.h>.

> -----------------------------------------

> -----------------------------------------

Hi.

I've seen you and other posters mentioning the failure to include
<stdlib.h> as an "error", and saying that the cast on malloc( ) could
hide the error.  While I agree that the cast would hide the omission of
<stdlib.h>, I am not so sure about why that is an "error".  If malloc( )
is the only function in your code that uses <stdlib.h>, then failure to
include it will not cause any compile/build error since malloc( ) is
defined in the standard C library.  If other places in your code require
<stdlib.h>, then those places will give you a warning (or error) for not
including it even if you cast malloc( ).  Or am I missing something?

Thanks
Dai

--
Daigoro Toyama
Software Engineer
Vista Development Corporation
http://vista.raima.com

Sat, 21 Oct 2000 03:00:00 GMT
Thought I knew what I was doing

Quote:

>I've seen you and other posters mentioning the failure to include
><stdlib.h> as an "error", and saying that the cast on malloc( ) could
>hide the error.  While I agree that the cast would hide the omission of
><stdlib.h>, I am not so sure about why that is an "error".  If malloc( )
>is the only function in your code that uses <stdlib.h>, then failure to
>include it will not cause any compile/build error since malloc( ) is
>defined in the standard C library.  If other places in your code require
><stdlib.h>, then those places will give you a warning (or error) for not
>including it even if you cast malloc( ).  Or am I missing something?

The issue isn't about getting to the code for 'malloc' itself, because
as you point out, that's in the library whether or not you include
the header file (on any real-world implementation I know of).  The point
is that you need to supply a declaration for 'malloc' before you call it.
Most programmers would call this a "prototype for 'malloc'", although
technically that's not quite the same thing.

The easiest way to declare 'malloc' is to include <stdlib.h>, though
if you really wanted to, it's equally valid to supply an explicit
prototype yourself.

If you don't have a declaration in scope at the time you call a function,
it is assumed to return 'int'.  Since 'malloc' actually returns 'void *',
that's an error -- the compiler will generate code on the false assumption
that 'malloc' is returning an 'int'.  An obvious example of where this
would fail is if 'int' and 'void *' occupied a different number of bytes;
there are more subtle ways it could go wrong.

With many implementations, though, it *would* still work, which doesn't
exactly help clarify the issue.

Bottom line:
It isn't always necessary to include the header files for the functions
you use, but 'malloc' is one case where it *is* required.  Since it's
hard to tell which functions do and do not require the inclusion of the
headers, and since, even when a header is not strictly required, it
may help catch particular coding errors, it's always good practice to
include the right header whenever you use a standard library function.

Cheers,
Richard
--
Richard Stamp
Churchill College, Cambridge

Sat, 21 Oct 2000 03:00:00 GMT
Thought I knew what I was doing

Quote:

>says...

>> Don't forget to test the result of malloc() for failure and to
>> #include <stdlib.h> for an appropriate prototype. The case is not
required
>> in C and can hide (but not fix) errors such as failure to include
<stdlib.h>.

>> -----------------------------------------

>> -----------------------------------------

>Hi.

>I've seen you and other posters mentioning the failure to include
><stdlib.h> as an "error", and saying that the cast on malloc( ) could
>hide the error.  While I agree that the cast would hide the omission of
><stdlib.h>, I am not so sure about why that is an "error".

Because malloc() does not return int, which is the default for C language
programs.  The malloc() function returns a void pointer.  Suppose that on
system "x" an int is 4 bytes in size and a void pointer is 8.  Do you see
the difficulties that may arise?

Quote:
>If malloc( )
>is the only function in your code that uses <stdlib.h>, then failure to
>include it will not cause any compile/build error since malloc( ) is
>defined in the standard C library.

BZZT.  Thanks for playing.  It is not typed correctly by default.

Quote:
>If other places in your code require
><stdlib.h>, then those places will give you a warning (or error) for not
>including it even if you cast malloc( ).  Or am I missing something?

Any function that does not return int MUST be prototyped as to return type.
Any function that does not take an int as one of its parameters SHOULD be
prototyped as to argument type.  Any function which is varadic MUST be
prototyped as varadic.  IMO, any missing prototype for a library function is
a code defect.  Even if it returns int and has no parameters.  YMMV.
--
Hypertext C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-FAQ ftp: ftp://rtfm.mit.edu, C-FAQ Book: ISBN 0-201-84519-9
Try "C Programming: A Modern Approach" ISBN 0-393-96945-2
Want Software?  Algorithms?  Pubs? http://www.infoseek.com

Sat, 21 Oct 2000 03:00:00 GMT
Thought I knew what I was doing

Quote:

> I've seen you and other posters mentioning the failure to include
> <stdlib.h> as an "error", and saying that the cast on malloc( ) could
> hide the error.  While I agree that the cast would hide the omission of
> <stdlib.h>, I am not so sure about why that is an "error".

It's an error because, in the abcense of a correct prototype, 'malloc()'
is implicitly defined to return 'int.' (The parameters implicitly assumed
depend on what you pass the first time you call the function.)

The point is that an implicit declaration is created, and this implicit
declaration does not match the standard one.

--
(initiator of the campaign for grumpiness where grumpiness is due in c.l.c)

Attempting to write in a hybrid which can be compiled by either a C compiler
or a C++ compiler produces a compromise language which combines the drawbacks
of both with the advantages of neither.

Sat, 21 Oct 2000 03:00:00 GMT
Thought I knew what I was doing

Quote:

> > Don't forget to test the result of malloc() for failure and to
> > #include <stdlib.h> for an appropriate prototype. The case is not required
> > in C and can hide (but not fix) errors such as failure to include <stdlib.h>.

> I've seen you and other posters mentioning the failure to include
> <stdlib.h> as an "error", and saying that the cast on malloc( ) could
> hide the error.  While I agree that the cast would hide the omission of
> <stdlib.h>, I am not so sure about why that is an "error".  If malloc( )
> is the only function in your code that uses <stdlib.h>, then failure to
> include it will not cause any compile/build error since malloc( ) is
> defined in the standard C library.  If other places in your code require
> <stdlib.h>, then those places will give you a warning (or error) for not
> including it even if you cast malloc( ).  Or am I missing something?

When malloc() isn't prototyped (correctly), the compiler will assume it
returns an int by default.  It doesn't though, but the compiler might
not know that.  It will happily generate calls to malloc() assuming it
returns an int argument, which will cause problems if the calling
conventions of int-returning and void*-returning functions are
different.

As you can see, it is an error not to correctly prototype malloc(), so
stdlib.h must be included if you intend to use it, or you can prototype
it yourself if you prefer to.  Casting hides the error of not including
stdlib.h, but that does not mean it is okay to shut the compiler up like
that.

--

I believe we can change anything.
I believe in my dream.
- Joe Satriani

Sat, 21 Oct 2000 03:00:00 GMT
Thought I knew what I was doing

[snip]

Quote:
>My point is simply that using an unprototyped function
>will generate (at least) a warning.

I don't believe this is true.  It SHOULD produce at least a warning.  But on
some compiler settings it will not produce one [for some of my compilers]
and I do not believe that there is a requirement in the standard that it
produce a diagnostic.
[snip]
--
Hypertext C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-FAQ ftp: ftp://rtfm.mit.edu, C-FAQ Book: ISBN 0-201-84519-9
Try "C Programming: A Modern Approach" ISBN 0-393-96945-2
Want Software?  Algorithms?  Pubs? http://www.infoseek.com

Sat, 21 Oct 2000 03:00:00 GMT
Thought I knew what I was doing

Quote:

> says...

>> Don't forget to test the result of malloc() for failure and to
>> #include <stdlib.h> for an appropriate prototype. The case is not required
>> in C and can hide (but not fix) errors such as failure to include <stdlib.h>.

> Hi.
> I've seen you and other posters mentioning the failure to include
> <stdlib.h> as an "error", and saying that the cast on malloc( ) could
> hide the error.  While I agree that the cast would hide the omission of
> <stdlib.h>, I am not so sure about why that is an "error".  If malloc( )
> is the only function in your code that uses <stdlib.h>, then failure to
> include it will not cause any compile/build error since malloc( ) is
> defined in the standard C library.  If other places in your code require

That malloc() is defined in the standard C library is beside the point. If
you fail to prototype your functions, the compiler will issue a warning.
To wit:

--- begin clc.c ---
#include <stdio.h>
int main(void)
{
int *foo;
if ((foo = malloc(10 * sizeof(int))) == NULL)
printf("malloc(10) failed\n");
else {
printf("malloc(10) succeeded\n");
free(foo);
}
return 0;

Quote:
}

--- end clc.c ---
Compiling the above with gcc 2.7.2.3 with
gcc -Wall --pedantic --ansi clc.c -o clc
yields the following:

% clc.c: In function `main':
% clc.c:6: warning: implicit declaration of function `malloc'
% clc.c:6: warning: assignment makes pointer from integer without a cast
% clc.c:10: warning: implicit declaration of function `free'

Casting malloc's return value to int * silenced the cast, which is what
we would expect. However, if I #include <stdlib.h>, all three of the
warnings disappear. My point is simply that using an unprototyped function
will generate (at least) a warning.

Quote:
> <stdlib.h>, then those places will give you a warning (or error) for not
> including it even if you cast malloc( ).  Or am I missing something?

As pointed out, the warning goes away when you cast malloc().  I'll leave
it to the language lawyers to explain why and to argue the point whether
it is an error or not.
Quote:
> Thanks
> Dai

Sun, 22 Oct 2000 03:00:00 GMT
Thought I knew what I was doing

says...

Quote:

> [snip]
> >My point is simply that using an unprototyped function
> >will generate (at least) a warning.

> I don't believe this is true.  It SHOULD produce at least a warning.  But on
> some compiler settings it will not produce one [for some of my compilers]
> and I do not believe that there is a requirement in the standard that it
> produce a diagnostic.

Thanks everyone for the replies.  My point is summed up very well as
above by Dan Corbit.  My understanding was that the ANSI standard does
not require function prototyping.  Should that be the case, using
malloc() in your code without including <stdlib.h> should not be
considered an error even though it is probably an extremely bad practice.

I am not arguing against the use of prototypes.  In fact, I never fail to
use prototypes in my C code, whether or not it's a standard C function or
one of my own.  I just wanted to see the reason behind so many people on
this group considering this practice an error.

Regards,
Dai

--
Daigoro Toyama
Software Engineer
Vista Development Corporation
http://vista.raima.com

Sun, 22 Oct 2000 03:00:00 GMT
Thought I knew what I was doing

|> Thanks everyone for the replies.  My point is summed up very well as
|> above by Dan Corbit.  My understanding was that the ANSI standard does
|> not require function prototyping.  Should that be the case, using
|> malloc() in your code without including <stdlib.h> should not be
|> considered an error even though it is probably an extremely bad practice.

But it *is* an error.

Saying that modern C doesn't require prototypes is somewhat correct,
but it is more misleading than anything else.  If you want to really
qualify your statement, you have to explain it a bit further.

"C does not require prototypes .."

1) ".. unless the function returns something other than int."

When a C translator encounters a function for which there is no
prototype in scope, it implicitly declares it as a function
taking some unspecified (but fixed) number of arguments which
returns an int.  For some functions, this may be an accurate
enough description to get by.

But for some (i.e., malloc()) it is not.  malloc() certainly does
not return an int, and so a prototype is required.  It's easy to
imagine the problems that can arise on platforms where the size
of a void pointer is larger than the size of an int.

Hence a prototype for malloc() is required before it is used.

2) ".. unless the function takes an argument of type char, signed
char, unsigned char, unsigned/signed short, or float."

When a C translator encounters a function for which there is no
prototype in scope, it applies what are called the "default
argument promotions" to each of the passed arguments.  In
particular, character and short types are promoted to ints, and
float types are promoted to doubles.  These same promotions
apply to variadic functions such as printf().  (As it turns out,
this is the reason why the "%f" specifier is used for both
float and double arguments .. floats are never passed to
printf() "as floats"; they are always promoted to doubles.)

In other words, if I have a function somewhere declared as

void foo(char c);

and later call it with no prototype in scope, as in

char c = 'a';
foo(c);

then foo() will "receive" an int argument, even though it is
expecting a char.  This is most assuredly not what you want.
Therefore, here's another case where a prototype is needed.

3) ".. unless the function is variadic."

functions differently than non-variadic functions.  Let's say
that we have a function and a hypothetical implementation:

int foo(int a, int b, int c);

Upon calling this function, each of the arguments are placed in
registers (as opposed to being placed on the stack, which we
might expect from a "traditional" implementation.)

But now let's look at another declaration:

int bar(int a, ...);

Upon calling *this* function, the implementation generates
code to pass all of the arguments on the stack.  In other
words, we have two completely different mechanisms for
passing arguments to functions, based on whether the function
is variadic or not.  (By the way, this type of implementation
is fairly common.)

But in order to ensure that the arguments are properly passed,
the implementation has to *know* whether or not the function
is variadic.  Because of this, a prototype for bar() *must* be
in scope when it is called.

Another example is the seemingly-innocent C program:

int main(void) {
printf("Hello, world!\n");
return 0;
}

This *looks* correct enough, but isn't; since a variadic
function is called without a prototype for it in scope, this
piece of code invokes undefined behavior.

If any three of the above conditions are not met, then a prototype
is required for the function in question.

As I'm sure you've already guessed, the *best* advice is simply to
prototype *every* function, even if it is technically allowable to
omit one because you can "get away with it" by the rules above.

Regards,

--
Chris Engebretson - Raytheon STX Corporation | Ph#: (605)594-6829
USGS EROS Data Center, Sioux Falls, SD 57198 | Fax: (605)594-6940

Opinions are not those of  Raytheon Systems Company  or the USGS.

Sun, 22 Oct 2000 03:00:00 GMT
Thought I knew what I was doing

Quote:

> [snip]

> When malloc() isn't prototyped (correctly), the compiler will assume it
> returns an int by default.  It doesn't though, but the compiler might
> not know that.  It will happily generate calls to malloc() assuming it
> returns an int argument, which will cause problems if the calling
> conventions of int-returning and void*-returning functions are
> different.

> As you can see, it is an error not to correctly prototype malloc(), so
> stdlib.h must be included if you intend to use it, or you can prototype
> it yourself if you prefer to.  Casting hides the error of not including
> stdlib.h, but that does not mean it is okay to shut the compiler up like
> that.

> --

Hi all.

I think I finally understand what this all means, and why omitting
<stdlib.h> and explicitly casting malloc() is really an error.  In
addition to the possible problem John explained above, I'd also imagine
that if the compiler assumes malloc() returns an int (as is the case when
you don't include <stdlib.h>), any returned value from malloc() larger
than the maximum limit of int (i.e. 64K) will be truncated to fit the
size of int before explicitly cast back to the pointer.  It can happen on
a system where the size of pointers is larger than that of integers (such
as Digital UNIX).

I appreciate all the information you guys have provided for me on this
issue.  I'm glad to be on this newsgroup.  I learn new things every day!

Regards,
Dai

--
Daigoro Toyama
Software Engineer
Vista Development Corporation
http://vista.raima.com

Sun, 22 Oct 2000 03:00:00 GMT
Thought I knew what I was doing

Quote:

> I think I finally understand what this all means, and why omitting
> <stdlib.h> and explicitly casting malloc() is really an error.  In
> addition to the possible problem John explained above, I'd also imagine
> that if the compiler assumes malloc() returns an int (as is the case when
> you don't include <stdlib.h>), any returned value from malloc() larger
> than the maximum limit of int (i.e. 64K) will be truncated to fit the
> size of int before explicitly cast back to the pointer.

The type "int" is simply not partibly combatible with any pointer type.
But the limit of "int" is *not* defined as 64K ! This is a
misconception. The C language defines the *minimum* range for an
"int" as -32767 to 32767. But a compiler is free to define other
larger ranges, like for instance some compiler have 32 bit "int"
instead of 16 bit. The compiler must however set the constants "INT_MIN"
and "INT_MAX" in <limits.h> the the correct upper and lower limits.

Stephan
(initiator of the campaign against grumpiness in c.l.c)

Mon, 23 Oct 2000 03:00:00 GMT

 Page 1 of 2 [ 23 post ] Go to page: [1] [2]

Relevant Pages