Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

"do ... while ((NULL + 1) - 1);" -- valid C?

30 views
Skip to first unread message

DAVID NEWALL

unread,
Aug 7, 1989, 10:20:31 AM8/7/89
to
I want to scan a string with fields separated by commas. To do this, I
wrote the following:
do
...
while ((s = strchr(s, ',') + 1) - 1);

I've been told that this is not valid C because, in the case that there
are no more fields (commas), strchr() returns NULL; and NULL + 1 is not
valid.

Comments, anyone?


David Newall Phone: +61 8 343 3160
Unix Systems Programmer Fax: +61 8 349 6939
Academic Computing Service E-mail: cc...@levels.sait.oz.au
SA Institute of Technology Post: The Levels, South Australia, 5095

Conor P. Cahill

unread,
Aug 7, 1989, 9:44:06 PM8/7/89
to
In article <10...@levels.sait.edu.au>, cc...@levels.sait.edu.au (DAVID NEWALL) writes:
>
> I've been told that this is not valid C because, in the case that there
> are no more fields (commas), strchr() returns NULL; and NULL + 1 is not
> valid.

NULL, in this case, is just a pointer that has the value 0. NULL + 1 is a valid
operations, however *(NULL+1) is not.

I wouldn't code the loop as you have displayed because one has to
spend time thinking about what the will is trying to do. A "better" method
would be something like:

do
...;
s = strchr(s,',');
while ( s++ != NULL );

Doug Gwyn

unread,
Aug 8, 1989, 5:09:26 PM8/8/89
to
In article <10...@levels.sait.edu.au> cc...@levels.sait.edu.au (DAVID NEWALL) writes:
-I've been told that this is not valid C because, in the case that there
-are no more fields (commas), strchr() returns NULL; and NULL + 1 is not
-valid.
-Comments, anyone?

You were told right. You're not allowed to perform pointer arithmetic
involving null pointers.

Doug Gwyn

unread,
Aug 8, 1989, 5:19:00 PM8/8/89
to
In article <9...@virtech.UUCP> cpc...@virtech.UUCP (Conor P. Cahill) writes:
>NULL + 1 is a valid operations, ...

No!

Bill Rust

unread,
Aug 9, 1989, 9:38:08 AM8/9/89
to


In my experience, NULL is always defined using the preprocessor line
"#define NULL 0" (or 0L). Since the while construct is relying on the
fact NULL is, in fact, 0, doing NULL + 1 - 1 is ok. I certainly wouldn't
recommend using it as a reference to memory. But, unless NULL is a
reserved word to your compiler, the compiler sees 0 + 1 - 1 and that is
ok.

Bill Rust (w...@ftp.com)

Doug Gwyn

unread,
Aug 9, 1989, 4:35:48 PM8/9/89
to
In article <6...@ftp.COM> w...@ftp.UUCP (Bill Rust) writes:
-In article <10...@smoke.BRL.MIL> gw...@brl.arpa (Doug Gwyn) writes:
->In article <9...@virtech.UUCP> cpc...@virtech.UUCP (Conor P. Cahill) writes:
->>NULL + 1 is a valid operations, ...
->No!
-In my experience, NULL is always defined using the preprocessor line
-"#define NULL 0" (or 0L).

That's not always true, but anyway it's irrelevant...

-Since the while construct is relying on the fact NULL is, in fact, 0,
-doing NULL + 1 - 1 is ok.

The code example was adding 1 to the return value from strchr().
strchr() does not return a preprocessor macro; it returns a null macro
(when it doesn't return a pointer to a valid char object). You are not
allowed to add 1 to a null pointer. If you happen to get away with it,
you're just lucky; it's not correct code.

In any event, if you rely on NULL being defined (for example in <stdio.h>)
as the source character string "0", then you're asking for trouble, since
it can be defined as any valid form of null pointer constant, including
for example "((void*)0)". Indeed, it's rather expected that standard-
conforming implementations are more likely to choose the latter form.
Your program may suddenly stop working when a new release of the compiler
is installed, or when you port it to another environment.

Doug Gwyn

unread,
Aug 9, 1989, 4:39:32 PM8/9/89
to
In article <10...@smoke.BRL.MIL> gw...@brl.arpa (Doug Gwyn) writes:
>strchr() does not return a preprocessor macro; it returns a null macro

That was supposed to say:

strchr() does not return a preprocessor macro; it returns a null pointer ...

Our stupid news system software wouldn't let me cancel the article so
that I could send a corrected version. I hope that this slip-up didn't
cause anybody too much confusion.

strchr(/*...*/)+1 is WRONG when strchr() returns a null pointer.

Chris Torek

unread,
Aug 9, 1989, 7:58:14 PM8/9/89
to
In article <6...@ftp.COM> w...@ftp.COM (Bill Rust) writes:
>In my experience, NULL is always defined using the preprocessor line
>"#define NULL 0" (or 0L).

NULL may correctly (by the pANS) be defined as `(void *)0'.

>Since the while construct is relying on the fact NULL is, in fact, 0,
>doing NULL + 1 - 1 is ok.

It is *if* two conditions hold:

0. NULL is `#define'd as an integral constant zero
rather than (void *)0, and
1. the loop actually reads `while (NULL + 1 - 1)'.

The latter did not hold in the original example, which was

do ... while ((s = index(s, ',') + 1) - 1);

The result of

<expression yeilding non nil character pointer> + 1

is a pointer to the character `beyond the one returned', so that

s = index("foo, bar", ',') + 1

winds up making s point to the space in "foo, bar"; but the
result of

<expression yeilding nil character pointer> + 1

is not defined.% On many machines it `just happens' to give the
address of byte number 1 in the machine; loading this into a machine
pointer register (e.g., for assignment to s) may cause a runtime trap.
In any case, its being undefined gives the system license to do
arbitrarily annoying things at this point. The `-1' after this
is thus irrelevant: like Humpty Dumpty, once a pointer is broken,
not all the King's horses nor all the King's persons%% can put it
back together again.
-----
% So *that* is how you get a butterfly! :-)
%% non-sexist noun :-) [too bad about `King']
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain: ch...@mimsy.umd.edu Path: uunet!mimsy!chris

D. Chadwick Gibbons

unread,
Aug 9, 1989, 8:08:36 PM8/9/89
to
In article <6...@ftp.COM> w...@ftp.UUCP (Bill Rust) writes:
|In my experience, NULL is always defined using the preprocessor line
|"#define NULL 0" (or 0L). Since the while construct is relying on the
|fact NULL is, in fact, 0, doing NULL + 1 - 1 is ok. I certainly wouldn't
|recommend using it as a reference to memory. But, unless NULL is a
|reserved word to your compiler, the compiler sees 0 + 1 - 1 and that is
|ok.

Bad assumption. In most decent implementations, NULL is indeed
defined as either 0 or 0L. But this can't be, and isn't, true in all
implementations, which immediately prohibts use of it, if for nothing else
than portability reasons. In many current implmentations, NULL is often
defined as ((char *)0) since it is the only "safe" thing to do--since many
programmers are not safe.

As defined by K&R2, NULL is an expression "with value 0, or such
cast to type void *." (A6.6, p.198) This allows implementations to define NULL
as (void *)0, which would cause your NULL +1 -1 to fail.

In spite of all that, why the hell would you want to use something
designed to designate a _nil pointer_ as an integer expression?! All of the
above is moot; NULL should not be used as an integer in an integer expression!
If using a symbolic is that important to you, do the ASCII thing:

#define NUL (0)

Or perhaps something a little more readable:

#define ZERO (0)

(Don't you feel sorry for those you don't know what a "0" means when they see
it inside code? I know I sure do.)
--
D. Chadwick Gibbons, ch...@lakesys.lakesys.com, ...!uunet!marque!lakesys!chad

Wolfgang Deifel

unread,
Aug 10, 1989, 4:55:56 AM8/10/89
to
cc...@levels.sait.edu.au (DAVID NEWALL) writes:

> do
> ...
> while ((s = strchr(s, ',') + 1) - 1);

>I've been told that this is not valid C because, in the case that there
>are no more fields (commas), strchr() returns NULL; and NULL + 1 is not
>valid.

Why should NULL + 1 not be valid ??? NULL is a pointer with the value 0
and you can add the integer 1 to it ( but you cannot access *s in the case
strchr is NULL of course ).

Wolfgang.

Robert A. Earl

unread,
Aug 10, 1989, 9:27:17 AM8/10/89
to
In article <6...@ftp.COM> w...@ftp.UUCP (Bill Rust) writes:
>In article <10...@smoke.BRL.MIL> gw...@brl.arpa (Doug Gwyn) writes:
>>In article <9...@virtech.UUCP> cpc...@virtech.UUCP (Conor P. Cahill) writes:
>>>NULL + 1 is a valid operations, ...
>>No!
>In my experience, NULL is always defined using the preprocessor line
>"#define NULL 0" (or 0L). Since the while construct is relying on the
>fact NULL is, in fact, 0, doing NULL + 1 - 1 is ok.
>Bill Rust (w...@ftp.com)


I have to disagree with Bill here. The NULL being
returned was from a string manipulation function...ie
not just a NULL but a (char *) NULL....I believe it is
illegal (or at least unportable) to add (char *)NULL + 1.


--
===========================================================
Name: Bob Earl Phone: (202) 872-6018 (wk)
UUCP: ...!uunet!wash08!rae98
BITNET: ...rae98@CAS (At least, that is what I'm told)

Chris Torek

unread,
Aug 11, 1989, 5:01:17 AM8/11/89
to
In article <9...@lakesys.UUCP> ch...@lakesys.UUCP (D. Chadwick Gibbons) writes:
>... In most decent implementations, NULL is indeed defined as either
>0 or 0L.

Right.

>But this can't be, and isn't, true in all implementations,

No and yes: it could be, but it is not.

>... In many current implmentations, NULL is often defined as ((char *)0)
>since it is the only "safe" thing to do [meaning `the only way the vendor
>can keep the authors of bad code happy'].

This is both unsafe and wrong, even if it does keep such authors happy.
Consider: If we write

char *cp;
int *ip;

ip = cp;

the compiler must issue some kind of diagnostic (it says so in the
proposed ANSI C specification, and it says in K&R-1 that this operation
is machine-dependent, and all quality compilers do indeed generate a
warning). This situation does not change if we write

ip = (char *)ip;

It does change if we write instead

ip = (int *)(char *)ip;

which puts the value in ip through two transformations (from
pointer-to-int to pointer-to-char, then from pointer-to-char to
pointer-to-int), and these two together are required to reproduce
the original value (this is something of a special case).

So: consider what happens if some implementer has wrongly put the line

#define NULL ((char *)0)

in <stdio.h> and <stdarg.h> and so forth, and we write

ip = NULL;

The compiler sees

ip = ((char *)0);

which, as far as the type system is concerned, is identical to

ip = cp;

---that is, it is machine dependent, and requires a warning. We can
(probably) eliminate the warning% by adding a cast:

ip = (int *)NULL;

which expands to

ip = (int *)((char *)0);

On *most* machines, this `just happens' to work. But if we look very
closely at the language definition, we find that it is not *required*
to work. The version of this that is required to work is instead

ip = (int *)(char *)(int *)0;

We are not allowed (outside of machine-dependent code) to change a
pointer-to-char into a pointer-to-int unless the pointer-to-char itself
came into existence as the result of a cast from a pointer-to-int. The
only way to *create* a nil-pointer-to-int in the first place is to
write (int *)0, or (in the proposed ANSI C) (int *)(void *)0.

Of course, the actual definition of NULL in <stdio.h> and <stdarg.h>
and so on is provided per machine, so if

int *ip = (int *)(char *)0;

`just happens' to work on that machine, the vendor could get away
with it. But

int *ip = NULL;

is guaranteed to work *without* generating warnings on any machine
where NULL is correctly defined, and one should not have to write

int *ip = (int *)NULL;

just to avoid getting warnings---nor should the compiler be silent
about code like

int *ip; char *cp; ip = cp;

The rest of <9...@lakesys.UUCP> is correct.
-----
% The (probably) in eliminating warnings refers to the fact that
a compiler can warn about anything it pleases:

% cc -o foo foo.c
cc: Warning: relative humidity and barometer pressure
indicate that thunderstorms are likely
cc: Warning: your shoelace is untied
cc: Warning: this code looks ugly
cc: Warning: your mother wears army boots
cc: Warning: Hey! Keep away from me with that axe!
cc: Warning: Ack! No, wait, I di(*&1to01llk

Chris Torek

unread,
Aug 11, 1989, 5:14:09 AM8/11/89
to
>> while ((s = strchr(s, ',') + 1) - 1)

In article <8...@ruso.UUCP> wolf...@ruso.UUCP (Wolfgang Deifel) writes:
>Why should NULL + 1 not be valid ??? NULL is a pointer with the value 0

>and you can add the integer 1 to it ....

NULL is not a pointer with the value 0, and 1 is not being added to
NULL here, but rather to a nil-pointer-to-char in the case in question.

NULL is a preprocessor macro; it expands to either an integral constant
zero (whose type is one of the integral types, e.g., int or short or long,
and whose value is zero) or to such a value cast to pointer-to-void
(whose type is pointer-to-void and whose value is unknowable).

A nil-pointer-to-char has type pointer-to-char and an ineffable value.
There is no way to talk about its value other than to say `it is a
nil pointer to char'. In particular, you cannot say what happens
when you add one to it.

david.f.prosser

unread,
Aug 11, 1989, 1:59:24 PM8/11/89
to
In article <18...@mimsy.UUCP> ch...@mimsy.UUCP (Chris Torek) writes:
>
> ip = (int *)((char *)0);
>
>On *most* machines, this `just happens' to work. But if we look very
>closely at the language definition, we find that it is not *required*
>to work. The version of this that is required to work is instead
>
> ip = (int *)(char *)(int *)0;
>
>We are not allowed (outside of machine-dependent code) to change a
>pointer-to-char into a pointer-to-int unless the pointer-to-char itself
>came into existence as the result of a cast from a pointer-to-int. The
>only way to *create* a nil-pointer-to-int in the first place is to
>write (int *)0, or (in the proposed ANSI C) (int *)(void *)0.

The pANS does guarantee that, for example,

0 == (void *)(int *)(char *)0

[3.2.2.3: "Two null pointers, converted through possibly different sequences
of casts to pointer types, shall compare equal."]

Therefore, I interpret the pANS as requiring

(int *)(char *)0

to have the same value as

(int *)0

(the nil-pointer-to-int, in your terminology)--not `just happening' to work.

Dave Prosser ...not an official X3J11 answer...

Doug Gwyn

unread,
Aug 11, 1989, 4:58:11 PM8/11/89
to
In article <18...@mimsy.UUCP> ch...@mimsy.UUCP (Chris Torek) writes:
> cc: Warning: this code looks ugly

I've seen this one (actually I think it was "expression too complex")

> cc: Warning: your mother wears army boots

You must be using our compiler..

Chris Torek

unread,
Aug 12, 1989, 1:50:30 AM8/12/89
to
>In article <18...@mimsy.UUCP> I suggested that

>> int *ip = (int *)(char *)0;

was not portable.

In article <14...@cbnewsl.ATT.COM> d...@cbnewsl.ATT.COM (david.f.prosser) writes:
>The pANS does guarantee that, for example,
> 0 == (void *)(int *)(char *)0
>[3.2.2.3: "Two null pointers, converted through possibly different sequences
>of casts to pointer types, shall compare equal."]
>
>Therefore, I interpret the pANS as requiring
> (int *)(char *)0
>to have the same value as
> (int *)0
>(the nil-pointer-to-int, in your terminology)--not `just happening' to work.

It does seem to say this. I missed this clause earlier. I find it
somewhat astonishing, actually. It makes carrying types around with
each nil pointer value rather difficult. (It would be nice for, e.g.,
a debugger to be able to say

location arr[300] contains (struct foo *)0

but the only way to do this is to have a different value for every kind
of nil, and this clause would then constrain pointer comparisons and/or
casts to `look past' the difference. Being able to tell what kind of
object---nil pointer or otherwise---resides in some memory location
would be of some use in tracking down stray-pointer bugs. Then again,
to do this right requires type tags everywhere, not just for nil pointers.)

Blair P. Houghton

unread,
Aug 12, 1989, 12:01:51 PM8/12/89
to
In article <10...@smoke.BRL.MIL> gw...@brl.arpa (Doug Gwyn) writes:

I got this one the other day:

cc: Warning: this is a riot; posting to comp.lang.c

--Blair
"Y'see, I was trying to
add two NULL pointers
together, and..."

Bjorn Engsig

unread,
Aug 14, 1989, 3:52:37 AM8/14/89
to
Article <37...@buengc.BU.EDU> by b...@buengc.bu.edu (Blair P. Houghton) says:
| --Blair
| "Y'see, I was trying to
| add two NULL pointers
| together, and..."
Can you add two pointers ?

[ No replies or followups please :-) ]
--
Bjorn Engsig, ORACLE Europe \ / "Hofstadter's Law: It always takes
Path: mcvax!orcenl!bengsig X longer than you expect, even if you
Domain: ben...@oracle.nl / \ take into account Hofstadter's Law"

Wolfgang Deifel

unread,
Aug 15, 1989, 6:26:56 AM8/15/89
to
cc...@levels.sait.edu.au (DAVID NEWALL) writes:

> while ((s = strchr(s, ',') + 1) - 1);

>I've been told that this is not valid C because, in the case that there
>are no more fields (commas), strchr() returns NULL; and NULL + 1 is not
>valid.

I think it's a difference if you write " NULL + 1 " ( which is non-
portable C, NULL is a machine dependent macro ) and " strchr(...) + 1 ".
strchr() is a function that returns always a legal value. If strchr fails
it will return (char*)0 ( regardless of the machine or the compiler ),
and here it's legal to add '1' ( the result is (char*)1 ).

----------------------------------------------------------------------------
Wolfgang Deifel
Dr. Ruff Software GmbH, 5100 Aachen, Juelicherstr. 65-67, W-Germany
uucp: ...!uunet{!mcvax}!unido!rwthinf!ruso!wolfgang - phone : +49 241 156038

Blair P. Houghton

unread,
Aug 15, 1989, 12:37:07 PM8/15/89
to
In article <474....@oracle.nl> ben...@oracle.nl (Bjorn Engsig) writes:
>Article <37...@buengc.BU.EDU> by b...@buengc.bu.edu (Blair P. Houghton) says:
>> "Y'see, I was trying to
>> add two NULL pointers
>> together, and..."
>
>Can you add two pointers ? [...] :-)

Well, _I_ can. :-)

--Blair
"But not in this dump."

Doug Gwyn

unread,
Aug 16, 1989, 12:27:07 AM8/16/89
to
In article <8...@ruso.UUCP> wolf...@ruso.UUCP (Wolfgang Deifel) writes:
>it will return (char*)0 ( regardless of the machine or the compiler ),
>and here it's legal to add '1' ( the result is (char*)1 ).

What is this, a time-shift phenomenon? We keep getting a sprinkling
of articles making this incorrect claim. It is NOT legal to perform
arithmetic on a null pointer.

Chris Torek

unread,
Aug 16, 1989, 8:57:19 AM8/16/89
to
In article <8...@ruso.UUCP> wolf...@ruso.UUCP (Wolfgang Deifel) writes:
>I think it's a difference if you write " NULL + 1 " ( which is non-
>portable C, NULL is a machine dependent macro ) and " strchr(...) + 1 ".

There is a difference. However:

>strchr() is a function that returns always a legal value. If strchr fails
>it will return (char*)0 ( regardless of the machine or the compiler ),
>and here it's legal to add '1' ( the result is (char*)1 ).

this is what we just got finished saying is false: it is NOT legal to
add 1 to (char *)0; indeed, it is not legal to add 1 to any of the
various infinite varieties of nil pointer.

Ruud Harmsen

unread,
Aug 16, 1989, 9:06:57 AM8/16/89
to
In article <18...@mimsy.UUCP> ch...@mimsy.UUCP (Chris Torek) writes:
>Consider: If we write
> char *cp;
> int *ip;
> ip = cp;
>
>the compiler must issue some kind of diagnostic (it says so in the
>proposed ANSI C specification, and it says in K&R-1 that this operation
>is machine-dependent, ...

I suppose this is machine-dependent because of alignment: char-pointers can
point to just about anywhere, but int-pointers on many machines have to be
aligned properly. My question is: can I make sure in my program, that
though generally non-portable this IS portable? I tried this once in the
following way:
The char-pointer gets its value from malloc, which the manual says gives
pointers properly aligned for any type. I never change that char-pointer
other than by adding multiples of sizeof(int) to it.
Is a "ip = cp" guaranteed safe under these conditions, so can I ignore
the compiler-warning?

DAVID NEWALL

unread,
Aug 17, 1989, 11:15:36 AM8/17/89
to
A while ago, cc...@levels.sait.edu.au (That's me!) wrote:
> do
> ...
> while ((s = strchr(s, ',') + 1) - 1);
>
> I've been told that this is not valid C

Thanks, everyone, for your opinions. I'll remember the rule in future:
(Offsets to NULL are non-portable, and should never be used).

Chris Torek

unread,
Aug 18, 1989, 9:46:14 AM8/18/89
to
>In article <18...@mimsy.UUCP> I noted that, given

>> char *cp;
>> int *ip;
>> ip = cp;
an `ANSI C compiler' (not that any exist yet; the standard is still in
the `proposed' state)
>>must issue some kind of diagnostic ....

In article <5...@targon.UUCP> ru...@targon.UUCP (Ruud Harmsen) writes:
>I suppose this is machine-dependent because of alignment: char-pointers can
>point to just about anywhere, but int-pointers on many machines have to be
>aligned properly.

This is at least one reason, if not the only reason. I know of no other
reason, and the (proposed) standard makes various constraints that may
eventually prove to eliminate other objections to such pointer conversions.

>My question is: can I make sure in my program, that though generally
>non-portable this IS portable? I tried this once in the following way:
>The char-pointer gets its value from malloc, which the manual says gives
>pointers properly aligned for any type. I never change that char-pointer
>other than by adding multiples of sizeof(int) to it.
>Is a "ip = cp" guaranteed safe under these conditions, so can I ignore
>the compiler-warning?

I believe it is safe, which is not the same as its being safe. (It is
much harder, given some property P, to prove based on the proposed
standard that, for all x, P(x) holds. In general, it is easier to come
up with some y for which P(y) does not hold. Here I cannot think of
any such y. Coming up with y's [or maybe they are y-nought's :-) ]
is good exercise for those who propose adding features to the standard.)

david.f.prosser

unread,
Aug 18, 1989, 10:27:49 AM8/18/89
to
In article <5...@targon.UUCP> ru...@targon.UUCP (Ruud Harmsen) writes:
>I suppose this is machine-dependent because of alignment: char-pointers can
>point to just about anywhere, but int-pointers on many machines have to be
>aligned properly. My question is: can I make sure in my program, that
>though generally non-portable this IS portable? I tried this once in the
>following way:
>The char-pointer gets its value from malloc, which the manual says gives
>pointers properly aligned for any type. I never change that char-pointer
>other than by adding multiples of sizeof(int) to it.
>Is a "ip = cp" guaranteed safe under these conditions, so can I ignore
>the compiler-warning?

Almost. Strictly speaking, malloc must return a pointer to an object that
can be accessed by a type commensurate with its size in bytes. For example,
``malloc(1)'' need not return a pointer that is appropriately aligned for a
pointer-to-int.

Moreover, it may well be possible to argue that unless the requested size
is a multiple of the size of an int, the returned pointer need not be
aligned appropriately for an int. For example, ``malloc(5)''.

However, the rest of your conditions are sufficient for the guarantee of
correct behavior.

Doug Gwyn

unread,
Aug 18, 1989, 5:52:53 PM8/18/89
to
In article <5...@targon.UUCP> ru...@targon.UUCP (Ruud Harmsen) writes:
>Is a "ip = cp" guaranteed safe under these conditions, so can I ignore
>the compiler-warning?

If you use a cast it is.

Steve Summit

unread,
Aug 20, 1989, 2:04:22 AM8/20/89
to
In article <15...@cbnewsl.ATT.COM> d...@cbnewsl.ATT.COM (david.f.prosser) writes:
>Strictly speaking, malloc must return a pointer to an object that
>can be accessed by a type commensurate with its size in bytes.
>Moreover, it may well be possible to argue that unless the requested size
>is a multiple of the size of an int, the returned pointer need not be
>aligned appropriately for an int. For example, ``malloc(5)''.

I hope not. This would break the variable-sized structure trick
(discussed here at length not long ago):

struct string
{
int length;
char text[1]; /* actually text[length] */
};

where we allocate a "string" with something like:

(struct string *)malloc(sizeof(struct string)-1+stringlen)

Henry Spencer says that Dennis Ritchie calls this "unwarranted
chumminess with the compiler," but it's widely used.

(Note that (struct string *)malloc(sizeof(struct string)) _would_
work, since sizeof(struct string) will typically be 2*sizeof(int).)

Steve Summit
s...@adam.pika.mit.edu

Casper H.S. Dik

unread,
Aug 20, 1989, 7:32:30 AM8/20/89
to
In article <5...@targon.UUCP> ru...@targon.UUCP (Ruud Harmsen) writes:
>
>I suppose this is machine-dependent because of alignment: char-pointers can
>point to just about anywhere, but int-pointers on many machines have to be
>aligned properly. My question is: can I make sure in my program, that
>though generally non-portable this IS portable? I tried this once in the
>following way:
>The char-pointer gets its value from malloc, which the manual says gives
>pointers properly aligned for any type. I never change that char-pointer
>other than by adding multiples of sizeof(int) to it.
>Is a "ip = cp" guaranteed safe under these conditions, so can I ignore
>the compiler-warning?

No. It is not safe. If you ever want to run your program on a Data General
MV, among others, you should use "ip = (int *) cp".

Since pointers to anything except char are word aligned on MV machines,
they decided that they could drop the last bit of the address and shift it.

A char pointer pointing to the second byte of memory is represented with
0x2. A word pointer to the same location is represented by 0x1.

This gave problems when porting programs. Most programmers write
"newp = (type *) malloc (sizeof type)"

but many forget the cast to char with free:

"free(oldp)" instead of "free((char *) oldp)"

This works fine in most cases, but not on machines that shift pointers
when casting.

--cd
Casper H.S. Dik VCP/HIP: +31205922022
University of Amsterdam | cas...@fwi.uva.nl
The Netherlands | casper%fwi.u...@hp4nl.nluug.nl

Ruud Harmsen

unread,
Aug 22, 1989, 5:09:00 AM8/22/89
to
In article <7...@janus.UUCP> cas...@fwi.uva.nl (Casper H.S. Dik) writes:
>> The char-pointer gets its value from malloc, and I never change that char-
>> pointer other than by adding multiples of sizeof(int) to it. Is a "ip =

>> cp" guaranteed safe under these conditions, so can I ignore the compiler-
>> warning?
>No. It is not safe. If you ever want to run your program on a Data General
>MV, among others, you should use "ip = (int *) cp".

You're right, of course. As a matter of fact, I did use the cast in my
program. Sorry I didn't mention that in the original article.

Ruud Harmsen

0 new messages