Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #5385 > unrolled thread

Questions Regarding Null and Casting

Started byBigChuck19 <bc19@mailinator.com>
First post2011-06-03 21:52 +0000
Last post2011-06-06 20:11 -0500
Articles 12 — 8 participants

Back to article view | Back to comp.lang.c


Contents

  Questions Regarding Null and Casting BigChuck19 <bc19@mailinator.com> - 2011-06-03 21:52 +0000
    Re: Questions Regarding Null and Casting Ian Collins <ian-news@hotmail.com> - 2011-06-04 10:13 +1200
      Re: Questions Regarding Null and Casting Ian Collins <ian-news@hotmail.com> - 2011-06-04 10:16 +1200
    Re: Questions Regarding Null and Casting Keith Thompson <kst-u@mib.org> - 2011-06-03 15:25 -0700
      Re: Questions Regarding Null and Casting Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-03 20:45 -0700
    Re: Questions Regarding Null and Casting pete <pfiland@mindspring.com> - 2011-06-03 18:38 -0400
    Re: Questions Regarding Null and Casting Angel <angel+news@spamcop.net> - 2011-06-03 23:23 +0000
      Re: Questions Regarding Null and Casting Keith Thompson <kst-u@mib.org> - 2011-06-03 17:24 -0700
    Re: Questions Regarding Null and Casting "J. J. Farrell" <jjf@bcs.org.uk> - 2011-06-04 00:45 +0100
    Re: Questions Regarding Null and Casting Keith Thompson <kst-u@mib.org> - 2011-06-03 17:27 -0700
    Re: Questions Regarding Null and Casting pete <pfiland@mindspring.com> - 2011-06-03 21:12 -0400
    Re: Questions Regarding Null and Casting Shao Miller <sha0.miller@gmail.com> - 2011-06-06 20:11 -0500

#5385 — Questions Regarding Null and Casting

FromBigChuck19 <bc19@mailinator.com>
Date2011-06-03 21:52 +0000
SubjectQuestions Regarding Null and Casting
Message-ID<isbl3d$lvh$1@speranza.aioe.org>
My textbook asserts that when checking if sufficient memory was allocated 
for a
dynamic variable using malloc(), a test should be made to determine 
whether
sufficient memory was actually allocated.  I understand the concept of 
checking
if the memory was allocated; the code confuses me, however.  E.g., a 
fragment
of code from the book is:

grades = (int *) malloc(numgrades * sizeof(int));
if (grades == (int *) NULL) {
   printf("Failed to allocate grades array");
   exit(1);

}

My question concerns the use of the cast (int *).  The book states that 
one
must write " if (grades == (int *) NULL) " because if there is 
insufficient
memory available, malloc() returns NULL, which is then cast into a 
pointer to
an integer by the (int *) preceding the call to malloc().  I do not 
understand
how NULL can be cast into anything, though, since I thought NULL was the
constant 0, or I guess its value is the constant 0.  To check if malloc()
returns NULL or not, why couldn't one write " if (grades == NULL) ".  I 
guess
the answer is that you can't write that because NULL was cast as a 
pointer to
an integer in the previous statement.  But what does it matter which data 
type
NULL  points to, as long as you determine that the address stored in 
grades is
NULL?

The use of a cast on NULL raises a few more questions.  Say I create a
character array called array.  After initializing all its entries, I then 
want
to clear the entire array by making each entry hold the null character.  I
could write something like the following to accomplish this:

for(i = 0; i < MAXTENTRIES; i++)
    array[i] = '\0';

Does the following loop perform the identical operation?

for(i = 0; i < MAXENTRIES; i++)
   array[i] = (char) NULL;

And I assume if the preceding code is valid, then one can cast NULL as 
any data
type; for instance,

for(i = 0; i < MAXENTRIES; i++)
   array[i] = (int) NULL;

would assign each entry the value of zero?

I am confused about the definition of NULL and the use of NULL; is it 
only used
when using pointers?  I am not sure, since the use of a cast on NULL 
seems to
indicate that one can make NULL any data type.

My final question concerns the use of NULL with a structure.  
If I define a structure, say,

typedef struct house {
   int floors;
   char owner[MAXSIZE];

} House;

and then declare h to be a variable of type house

House h;

Now does

h = (House) NULL;

have any meaning??  If so, what does the statement do?
Thanks for your help

Chuck

[toc] | [next] | [standalone]


#5388

FromIan Collins <ian-news@hotmail.com>
Date2011-06-04 10:13 +1200
Message-ID<94t4kkFbjiU13@mid.individual.net>
In reply to#5385
On 06/ 4/11 09:52 AM, BigChuck19 wrote:
> My textbook asserts that when checking if sufficient memory was allocated
> for a
> dynamic variable using malloc(), a test should be made to determine
> whether
> sufficient memory was actually allocated.  I understand the concept of
> checking
> if the memory was allocated; the code confuses me, however.  E.g., a
> fragment
> of code from the book is:
>
> grades = (int *) malloc(numgrades * sizeof(int));

grades = malloc(numgrades * sizeof(*)grades);

Would have been better.

> if (grades == (int *) NULL) {
>     printf("Failed to allocate grades array");
>     exit(1);
>
> }
>
> My question concerns the use of the cast (int *).  The book states that
> one
> must write " if (grades == (int *) NULL) " because if there is
> insufficient
> memory available, malloc() returns NULL, which is then cast into a
> pointer to
> an integer by the (int *) preceding the call to malloc().

The cast is both superfluous and in that case, confusing.

if (grades == (NULL)

is all that is required.

<snip>

> The use of a cast on NULL raises a few more questions.  Say I create a
> character array called array.  After initializing all its entries, I then
> want
> to clear the entire array by making each entry hold the null character.  I
> could write something like the following to accomplish this:
>
> for(i = 0; i<  MAXTENTRIES; i++)
>      array[i] = '\0';
>
> Does the following loop perform the identical operation?
>
> for(i = 0; i<  MAXENTRIES; i++)
>     array[i] = (char) NULL;

In practice, yes.  But it is a confusing way of writing (and the cast is 
superfluous again).

> And I assume if the preceding code is valid, then one can cast NULL as
> any data
> type; for instance,
>
> for(i = 0; i<  MAXENTRIES; i++)
>     array[i] = (int) NULL;
>
> would assign each entry the value of zero?

There could exist systems where NULL isn't zero...

> I am confused about the definition of NULL and the use of NULL; is it
> only used
> when using pointers?

That is is idiomatic use.  Use NULL for pointers and 0 elsewhere.

I am not sure, since the use of a cast on NULL
> seems to
> indicate that one can make NULL any data type.

A cast is the C equivalent of a sledge hammer.  If you want to force a 
square peg in round hole, use a big hammer.

> My final question concerns the use of NULL with a structure.
> If I define a structure, say,
>
> typedef struct house {
>     int floors;
>     char owner[MAXSIZE];
>
> } House;
>
> and then declare h to be a variable of type house
>
> House h;
>
> Now does
>
> h = (House) NULL;
>
> have any meaning??

No, it isn't valid.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#5389

FromIan Collins <ian-news@hotmail.com>
Date2011-06-04 10:16 +1200
Message-ID<94t4p4FbjiU14@mid.individual.net>
In reply to#5388
On 06/ 4/11 10:13 AM, Ian Collins wrote:
> On 06/ 4/11 09:52 AM, BigChuck19 wrote:
>> My textbook asserts that when checking if sufficient memory was allocated
>> for a
>> dynamic variable using malloc(), a test should be made to determine
>> whether
>> sufficient memory was actually allocated.  I understand the concept of
>> checking
>> if the memory was allocated; the code confuses me, however.  E.g., a
>> fragment
>> of code from the book is:
>>
>> grades = (int *) malloc(numgrades * sizeof(int));
>
> grades = malloc(numgrades * sizeof(*)grades);

Oops,

grades = malloc(numgrades * sizeof(*grades));

or

grades = malloc(numgrades * sizeof *grades);

> Would have been better.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#5392

FromKeith Thompson <kst-u@mib.org>
Date2011-06-03 15:25 -0700
Message-ID<lntyc6imc4.fsf@nuthaus.mib.org>
In reply to#5385
BigChuck19 <bc19@mailinator.com> writes:
> My textbook asserts that when checking if sufficient memory was
> allocated for a dynamic variable using malloc(), a test should be made
> to determine whether sufficient memory was actually allocated.  I
> understand the concept of checking if the memory was allocated; the
> code confuses me, however.  E.g., a fragment of code from the book is:
>
> grades = (int *) malloc(numgrades * sizeof(int));
> if (grades == (int *) NULL) {
>    printf("Failed to allocate grades array");
>    exit(1);
>
> }

This is rather poor code.  I presume that grades is declared as:
    int *grades;
which should have been shown along with the fragment.

Both casts are unnecessary, and can hide errors.  For an explation, see
section 7 of the comp.lang.c FAQ, <http://www.c-faq.com/>.

Rather than enumerating each problem (I see nearly one per line),
here's how I'd write it:

    grades = malloc(numrades * sizeof *grades);
    if (grades == NULL) {
        fprintf(stderr, "Failed to allocate grades array\n");
        exit(EXIT_FAILURE);
    }

> My question concerns the use of the cast (int *).  The book states
> that one must write " if (grades == (int *) NULL) " because if there
> is insufficient memory available, malloc() returns NULL, which is then
> cast into a pointer to an integer by the (int *) preceding the call to
> malloc().

The cast is an explicit conversion.  It's unnecessary because the value
of NULL will be implicitly converted to the type of grades (int*) before
it's compared.

It's more accurate to say that malloc() returns a null pointer.  NULL
is a macro that expands to a "null pointer constant".

>            I do not understand how NULL can be cast into anything,
> though, since I thought NULL was the constant 0, or I guess its value
> is the constant 0.

NULL expands to a null pointer constant.  It could be just a literal 0,
or the expression ((void*)0), or any of a number of other possibilities.
You don't need to care exactly what it expands to, just that evaluating
it *in a pointer context* yields a null pointer value.

>                     To check if malloc() returns NULL or not, why
> couldn't one write " if (grades == NULL) ".

You can and should.

>                                              I guess the answer is
> that you can't write that because NULL was cast as a pointer to an
> integer in the previous statement.  But what does it matter which data
> type NULL points to, as long as you determine that the address stored
> in grades is NULL?

The type of any pointer expression does matter a great deal.  But in
this case, there's a special-case rule that says a null pointer constant
will be implicitly converted to an appropriate pointer type.

> The use of a cast on NULL raises a few more questions.  Say I create a
> character array called array.  After initializing all its entries, I
> then want to clear the entire array by making each entry hold the null
> character.  I could write something like the following to accomplish
> this:
>
> for(i = 0; i < MAXTENTRIES; i++)
>     array[i] = '\0';

Ok.

> Does the following loop perform the identical operation?
>
> for(i = 0; i < MAXENTRIES; i++)
>    array[i] = (char) NULL;

It might, depending on how your implementation chooses to define NULL,
but it's a really bad idea.  NULL should be used *only* when you want a
null pointer value.  A null character is a very different thing.

(Unfortunately, on most systems the compiler won't warn you about
"(char) NULL".

> And I assume if the preceding code is valid, then one can cast NULL as
> any data type; for instance,
>
> for(i = 0; i < MAXENTRIES; i++)
>    array[i] = (int) NULL;
>
> would assign each entry the value of zero?

Don't do this either; see above.

> I am confused about the definition of NULL and the use of NULL; is it
> only used when using pointers?  I am not sure, since the use of a cast
> on NULL seems to indicate that one can make NULL any data type.

Yes, it should be only used when you want a null pointer value.

Most casts are unnecessary, since C provides implicit conversions for
most of the cases where you need one.

> My final question concerns the use of NULL with a structure.  If I
> define a structure, say,
>
> typedef struct house {
>    int floors;
>    char owner[MAXSIZE];
>
> } House;
>
> and then declare h to be a variable of type house
>
> House h;
>
> Now does
>
> h = (House) NULL;
>
> have any meaning??  If so, what does the statement do?

No, it has no meaning at all.  It's not legal to cast to a struct
type -- and it wouldn't make any sense to convert NULL to a struct
type anyway.

Incidentally, your original article was very difficult to read.  It looks
like you wrote it with fairly long lines, and something split each
line into two parts, resulting in alternating long and short lines
by the time I saw it.  Keep each line in a posted article down to
70 or 72 columns.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#5414

FromTim Rentsch <txr@alumni.caltech.edu>
Date2011-06-03 20:45 -0700
Message-ID<kfnboyeuun4.fsf@x-alumni2.alumni.caltech.edu>
In reply to#5392
Keith Thompson <kst-u@mib.org> writes:

> BigChuck19 <bc19@mailinator.com> writes:
>[snip]
>
>> My question concerns the use of the cast (int *).  The book states
>> that one must write " if (grades == (int *) NULL) " because if there
>> is insufficient memory available, malloc() returns NULL, which is then
>> cast into a pointer to an integer by the (int *) preceding the call to
>> malloc().
>
> The cast is an explicit conversion.  It's unnecessary because the value
> of NULL will be implicitly converted to the type of grades (int*) before
> it's compared.  [snip]

Just an amusing note here.  6.5.9p4 says:

    Otherwise, at least one operand is a pointer.  If one
    operand is a pointer and the other is a null pointer
    constant, the null pointer constant is converted to the type
    of the pointer.  If one operand is a pointer to an object or
    incomplete type and the other is a pointer to a qualified or
    unqualified version of void, the former is converted to the
    type of the latter.

If NULL is defined as '(void*)0', then both of the last two
sentences apply, and each operand is converted to the type
of the other.

[toc] | [prev] | [next] | [standalone]


#5395

Frompete <pfiland@mindspring.com>
Date2011-06-03 18:38 -0400
Message-ID<4DE96267.29C3@mindspring.com>
In reply to#5385
BigChuck19 wrote:

> To check if malloc() returns NULL or not,
> why couldn't one write " if (grades == NULL) ".

One could; there's absolutely nothing wrong with it.


> Say I create a character array called array.
> After initializing all its entries, I then want
> to clear the entire array by making
> each entry hold the null character.  I
> could write something like the following to accomplish this:
> 
> for(i = 0; i < MAXTENTRIES; i++)
>     array[i] = '\0';
> 
> Does the following loop perform the identical operation?
> 
> for(i = 0; i < MAXENTRIES; i++)
>    array[i] = (char) NULL;

No.


> I am confused about the definition of NULL and the use of NULL;

It is best to use NULL in a pointer context
regardless of how any particular implementation defines NULL.

NULL expands to an implementation-defined null pointer constant.

An integral constant expression with the value 0, or such an
expression cast to type void * , is called a null pointer constant.

An integral constant expression shall have integral type and shall
only have operands that are integer constants, enumeration constants,
character constants, sizeof expressions, and floating constants that
are the immediate operands of casts.  Cast operators in an integral
constant expression shall only convert arithmetic types to integral
types, except as part of an operand to the sizeof operator.

-- 
pete

[toc] | [prev] | [next] | [standalone]


#5396

FromAngel <angel+news@spamcop.net>
Date2011-06-03 23:23 +0000
Message-ID<slrniuir6v.4ok.angel+news@pearlgates.net>
In reply to#5385
On 2011-06-03, BigChuck19 <bc19@mailinator.com> wrote:
> My textbook asserts that when checking if sufficient memory was allocated 
> for a
> dynamic variable using malloc(), a test should be made to determine 
> whether
> sufficient memory was actually allocated.  I understand the concept of 
> checking
> if the memory was allocated; the code confuses me, however.  E.g., a 
> fragment
> of code from the book is:
>
> grades = (int *) malloc(numgrades * sizeof(int));
> if (grades == (int *) NULL) {
>    printf("Failed to allocate grades array");
>    exit(1);
>
> }

Must be a very old book, this is a code example from the time when there
was no "void *" type and malloc() returned a value of type "char *".

Nowadays, malloc() returns a value of type "void *", which can be
assigned to any pointer without a cast.


As for NULL, this is a special pointer value that points to no valid
object and can't be dereferenced. On most implementations, this is
indeed a pointer value with all bits zero, but the standard doesn't
guarantee that. Like "void *", NULL is compatible with any pointer
type and no cast is needed.


-- 
"C provides a programmer with more than enough rope to hang himself.
C++ provides a firing squad, blindfold and last cigarette."
- seen in comp.lang.c

[toc] | [prev] | [next] | [standalone]


#5402

FromKeith Thompson <kst-u@mib.org>
Date2011-06-03 17:24 -0700
Message-ID<lnlixiigti.fsf@nuthaus.mib.org>
In reply to#5396
Angel <angel+news@spamcop.net> writes:
> On 2011-06-03, BigChuck19 <bc19@mailinator.com> wrote:
>> My textbook asserts that when checking if sufficient memory was
>> allocated for a dynamic variable using malloc(), a test should be
>> made to determine whether sufficient memory was actually allocated.
>> I understand the concept of checking if the memory was allocated; the
>> code confuses me, however.  E.g., a fragment of code from the book
>> is:
>>
>> grades = (int *) malloc(numgrades * sizeof(int));
>> if (grades == (int *) NULL) {
>>    printf("Failed to allocate grades array");
>>    exit(1);
>>
>> }
>
> Must be a very old book, this is a code example from the time when there
> was no "void *" type and malloc() returned a value of type "char *".

Not necessarily.  The code still works, it's just poor style.
Even K&R2 says to cast the result of malloc, though the errata page
says this needs to be rewritten.

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#5398

From"J. J. Farrell" <jjf@bcs.org.uk>
Date2011-06-04 00:45 +0100
Message-ID<isbrm1$r0l$1@dont-email.me>
In reply to#5385
BigChuck19 wrote:
> My textbook asserts

Others have given good answers to your questions. Could you tell us the 
title and author of the book please. Once you've done so, please destroy 
or hide it and get a book written by someone who has a clue about C.

Telling you to cast the return value from malloc() could be explained by 
the book having been written before 1989, but there's no excuse for 
telling you to cast NULL in that situation.

[toc] | [prev] | [next] | [standalone]


#5403

FromKeith Thompson <kst-u@mib.org>
Date2011-06-03 17:27 -0700
Message-ID<lnhb86igph.fsf@nuthaus.mib.org>
In reply to#5385
ram@zedat.fu-berlin.de (Stefan Ram) writes:
[...]
>   IIRC (can't access my reference sources right now)
>   »NULL« is not defined in C (except, when one also has
>
> #include <stdlib.h>
>
>   before), so I prefer »0«, or avoid it altogether as above.

NULL is defined in several C standard headers, including <stdlib.h>,
<stddef.h>, and <stdio.h>.  Since the program calls printf(),
it's safe to assume that <stdio.h> is already included.

(Well, actually, it's *not* safe to assume that, especially given
the snippet's other problems, but it *should* be.)

Personally, I prefer to use NULL rather than 0 simply because it's more
explicit.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#5406

Frompete <pfiland@mindspring.com>
Date2011-06-03 21:12 -0400
Message-ID<4DE9868E.2099@mindspring.com>
In reply to#5385
Stefan Ram wrote:
> 
> BigChuck19 <bc19@mailinator.com> writes:
> >grades = (int *) malloc(numgrades * sizeof(int));
> >if (grades == (int *) NULL) {
> >   printf("Failed to allocate grades array");
> >   exit(1);
> >}
> 
>   I'd write this as:
> 
> if( !grades )
> fprintf( stderr, "Failed to allocate grades array." ); else ...

That string literal might be better
if it had a newline character at the end.

-- 
pete

[toc] | [prev] | [next] | [standalone]


#5592

FromShao Miller <sha0.miller@gmail.com>
Date2011-06-06 20:11 -0500
Message-ID<isjqbv$olf$1@dont-email.me>
In reply to#5385
On 6/3/2011 4:52 PM, BigChuck19 wrote:
> My final question concerns the use of NULL with a structure.
> If I define a structure, say,
>
> typedef struct house {
>     int floors;
>     char owner[MAXSIZE];
>
> } House;
>
> and then declare h to be a variable of type house
>
> House h;
>
> Now does
>
> h = (House) NULL;
>
> have any meaning??  If so, what does the statement do?
> Thanks for your help

A 'struct' is an "aggregate type" but 'NULL' must be a "scalar type", so 
no.  This restriction doesn't have anything to do with 'NULL'.  The 
type-name in a cast must be a scalar type, no matter the value being cast.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web