473,395 Members | 1,608 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

undefined behavior or not undefined behavior? That is the question

#include <stdio.h>

struct foo { int example; struct bar *ptr; };

int main(void)
{
struct foo baz;
baz.ptr = NULL; /* Undefined behavior? */

return 0;
}
My second question is not related to undefined behavior.
I read that bitwise AND is equivalent to
"Multiplication modulus two" They made some notation
with something that looked like two Zs'

Anyone familiar with that?

However:

printf("%d\n", 10 & 42);

printf("%d\n", (10 * 42) % 2);

most certainly differ.

but they used ^ for AND and said:

a * b (mod 2) = a ^ b

--
nethlek
Nov 14 '05
66 2985
In <sl*******************@hehe.cl.cam.ac.uk> Jeremy Yallop <je****@jdyallop.freeserve.co.uk> writes:
Dan Pop wrote:
Unless C99 has completely screwed the concept of lvalue, lvalues
cannot have incomplete types.


Unfortunately, they can:

An lvalue is an expression with an object type or an incomplete type
other than void; if an lvalue does not designate an object when it
is evaluated, the behavior is undefined.

I'm not sure why the second part is there: the only example of an
expression of incomplete type that I know is an array name where the
definition of the array is not in scope, and even that is
questionable.


Here's another example:

struct foo;
struct foo *bar(void);
struct foo *p = bar();

*p is now an expression of incomplete type. But this still doesn't
explain why such an expression should qualify as an lvalue.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #51
[on "PDP-endian"-ness]

In article <news:c0**********@sunnews.cern.ch>
Dan Pop <Da*****@cern.ch> writes:
The PDP-11's successor, the VAX, had fixed that hardware design blunder
of its ancestor and was little endian over all the range of supported
types.
Well, except D-float -- but this is not an integral type and it has
"bit" as well as "byte" order issues, when one takes it apart
(because the bit-fields do not fall on "natural" byte boundaries).
There are exactly two byte orders that have survived and, by no
coincidence, they are the two entirely consistent ones.


I am willing to bet that at least one CPU architecture will resurrect
mixed-endian integers in its 32-to-64-bit transition. (I suspect
it will be an existing little-endian architecture that is heavily
stack-oriented, too.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #52
Dan Pop wrote:
In <sl*******************@hehe.cl.cam.ac.uk> Jeremy Yallop <je****@jdyallop.freeserve.co.uk> writes:
Dan Pop wrote:
Unless C99 has completely screwed the concept of lvalue, lvalues
cannot have incomplete types.


Unfortunately, they can:

An lvalue is an expression with an object type or an incomplete type
other than void; if an lvalue does not designate an object when it
is evaluated, the behavior is undefined.

I'm not sure why the second part is there: the only example of an
expression of incomplete type that I know is an array name where the
definition of the array is not in scope, and even that is
questionable.


Here's another example:

struct foo;
struct foo *bar(void);
struct foo *p = bar();

*p is now an expression of incomplete type. But this still doesn't
explain why such an expression should qualify as an lvalue.


I thought that dereferencing a pointer to an incomplete type was a
constraint violation, but I can't find any text in the standard to
that effect. The only thing I can find, in fact, is the above text,
which means that there's no requirement to diagnose such things.

This seems wrong: there's no need to dereference such pointers and
doing so can trivially be detected at compile time. This seems to me
to be a glaring flaw in the standard; in fact, the whole lvalue thing
seems a horrible mess in C99.

Jeremy.
Nov 14 '05 #53

On Wed, 11 Feb 2004, Jeremy Yallop wrote:

Dan Pop wrote:
Jeremy Yallop <je****@jdyallop.freeserve.co.uk> writes:
Dan Pop wrote:
Unless C99 has completely screwed the concept of lvalue, lvalues
cannot have incomplete types.

Unfortunately, they can:

An lvalue is an expression with an object type or an incomplete type
other than void; if an lvalue does not designate an object when it
is evaluated, the behavior is undefined.

I'm not sure why the second part is there: the only example of an
expression of incomplete type that I know is an array name where the
definition of the array is not in scope, and even that is
questionable.
Here's another example:

struct foo;
struct foo *bar(void);
struct foo *p = bar();

*p is now an expression of incomplete type.
Even simpler:
extern struct foo F;
F is now an lvalue of incomplete type.
But this still doesn't
explain why such an expression should qualify as an lvalue.


Because it's quite obviously not an rvalue; it has a well-defined
address, for example.
I thought that dereferencing a pointer to an incomplete type was a
constraint violation,
It is. However, the expression *p doesn't necessarily dereference
p; you could have written &(*p), or (*p)[0] (both of which are legal
operations in C), or you could have written sizeof(*p) or (*p)[42]
(both of which are constraint violations in C, but still don't
involve dereferencing p). Or a*p->b. ;-)
but I can't find any text in the standard to
that effect. The only thing I can find, in fact, is the above text,
which means that there's no requirement to diagnose such things.


I'm almost certain it *is* a constraint violation to do anything
to an incompletely-typed object other than take its address; but
I have not looked for textual support yet. I'll let you know in
a few hours, if nobody else does first.

HTH,
-Arthur

Nov 14 '05 #54
Chris Torek wrote:
[on "PDP-endian"-ness]

In article <news:c0**********@sunnews.cern.ch>
Dan Pop <Da*****@cern.ch> writes:
The PDP-11's successor, the VAX, had fixed that hardware design blunder
of its ancestor and was little endian over all the range of supported
types.

Well, except D-float -- but this is not an integral type and it has
"bit" as well as "byte" order issues, when one takes it apart
(because the bit-fields do not fall on "natural" byte boundaries).

There are exactly two byte orders that have survived and, by no
coincidence, they are the two entirely consistent ones.

I am willing to bet that at least one CPU architecture will resurrect
mixed-endian integers in its 32-to-64-bit transition. (I suspect
it will be an existing little-endian architecture that is heavily
stack-oriented, too.)


Have in mind though, that mixed-mode architectures make things more
difficult than it should be...

--
#include <stdio.h>
#define p(s) printf(#s" endian")
int main(void){int v=1;*(char*)&v?p(Little):p(Big);return 0;}

Giannis Papadopoulos
http://dop.users.uth.gr/
University of Thessaly
Computer & Communications Engineering dept.
Nov 14 '05 #55
Arthur J. O'Dwyer wrote:
On Wed, 11 Feb 2004, Jeremy Yallop wrote:
I thought that dereferencing a pointer to an incomplete type was a
constraint violation,


It is.


Which constraint does it violate?

Jeremy.
Nov 14 '05 #56

In article <sl*******************@hehe.cl.cam.ac.uk>, Jeremy Yallop <je****@jdyallop.freeserve.co.uk> writes:
Arthur J. O'Dwyer wrote:
On Wed, 11 Feb 2004, Jeremy Yallop wrote:
I thought that dereferencing a pointer to an incomplete type was a
constraint violation,


It is.


Which constraint does it violate?


I think Arthur's wrong. Both 9899-1990 and N869 have a constraint for
the * unary operator, but it says only that the operand shall have
pointer type, not that the pointed-to type be complete. Contrast that
with, say, the constraint for the sizeof operator, which specifically
forbids incomplete types (though not, obviously, pointer types where
the pointed-to type is incomplete). Of course I may have missed some
other constraint elsewhere in the standard.

Also contrast with the constraint for array subscripting, which requires
that the first operand have "pointer to object type" - so dereferencing
a pointer to an incomplete type using array subscripting syntax would
be a constraint violation. (By 6.1.2.5 (C90) / 6.2.5 (N869), incomplete
types are not object types, so pointers to incomplete types are not
pointers to object types.)

In short:

extern struct foo *P;
*P; /* no constraint violation */
P[0]; /* constraint violation */
--
Michael Wojcik mi************@microfocus.com

He described a situation where a man is there to feed a dog and the dog is
there to keep the man from touching the equipment. -- Anthony F. Giombetti
Nov 14 '05 #57
In <c0*********@enews2.newsguy.com> Chris Torek <no****@torek.net> writes:
[on "PDP-endian"-ness]

In article <news:c0**********@sunnews.cern.ch>
Dan Pop <Da*****@cern.ch> writes:
The PDP-11's successor, the VAX, had fixed that hardware design blunder
of its ancestor and was little endian over all the range of supported
types.


Well, except D-float -- but this is not an integral type and it has
"bit" as well as "byte" order issues, when one takes it apart
(because the bit-fields do not fall on "natural" byte boundaries).


And D-float was supported exclusively for PDP-11 compatibility reasons.
The "native" double precision format of the VAX was G-float (having a
far wider range than the D-float).
There are exactly two byte orders that have survived and, by no
coincidence, they are the two entirely consistent ones.


I am willing to bet that at least one CPU architecture will resurrect
mixed-endian integers in its 32-to-64-bit transition. (I suspect
it will be an existing little-endian architecture that is heavily
stack-oriented, too.)


Which one would be that?

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #58
Dan Pop wrote:

In <c0*********@enews2.newsguy.com>
Chris Torek <no****@torek.net> writes:
[on "PDP-endian"-ness]
There are exactly two byte orders that have survived and, by no
coincidence, they are the two entirely consistent ones.


I am willing to bet that at least one CPU architecture will resurrect
mixed-endian integers in its 32-to-64-bit transition. (I suspect
it will be an existing little-endian architecture that is heavily
stack-oriented, too.)


Which one would be that?


In the context of this newsgroup, I don't think it's worthwhile
to memorize a subset of the allowable configurations,
which are extant today. I don't even think it's valid to claim
that you know all the extant ones.

When is the Death Station 9000 paradigm,
(any allowable configuration which invalidates your code)
for the abstract machine, appropriate on this newsgroup ?

--
pete
Nov 14 '05 #59

On Thu, 12 Feb 2004, Michael Wojcik wrote:

Jeremy Yallop <je****@jdyallop.freeserve.co.uk> writes:
Arthur J. O'Dwyer wrote:
On Wed, 11 Feb 2004, Jeremy Yallop wrote:
> I thought that dereferencing a pointer to an incomplete type was a
> constraint violation,

It is.
Which constraint does it violate?


I think Arthur's wrong.


I guess I am. Having looked very carefully at N869, I don't see
any evidence that '*P', where P is a pointer to an incomplete type,
violates any constraints.
Both 9899-1990 and N869 have a constraint for
the * unary operator, but it says only that the operand shall have
pointer type, not that the pointed-to type be complete. Contrast that
with, say, the constraint for the sizeof operator, which specifically
forbids incomplete types (though not, obviously, pointer types where
the pointed-to type is incomplete). Of course I may have missed some
other constraint elsewhere in the standard.

Also contrast with the constraint for array subscripting, which requires
that the first operand have "pointer to object type" - so dereferencing
a pointer to an incomplete type using array subscripting syntax would
be a constraint violation. (By 6.1.2.5 (C90) / 6.2.5 (N869), incomplete
types are not object types, so pointers to incomplete types are not
pointers to object types.)

In short:

extern struct foo *P;
*P; /* no constraint violation */
P[0]; /* constraint violation */


I think you're right; but I don't understand why the asymmetry
here. Why does the Standard allow '*P' but not 'P[0]'? (It's
obvious enough why it doesn't allow 'P[foo]', but I would have
extended that to make '*P' invalid, rather than making a seemingly
arbitrary distinction between the two indirection operators.)

-Arthur
Nov 14 '05 #60
In message <c0**********@sunnews.cern.ch>
Da*****@cern.ch (Dan Pop) wrote:
In <ch*********************************@slb-newsm1.svr.pol.co.uk> Christian Bau <ch***********@cbau.freeserve.co.uk> writes:
In article <c0**********@sunnews.cern.ch>, Da*****@cern.ch (Dan Pop)
wrote:

It is not just a matter of the architecture, it is also a matter of the
compiler. Many architectures in use today are based on 32 bit words. To
implement "long long" and "unsigned long long", the compiler typically
uses two 32 bit words. There is no technical reason why one of those
words should be first in memory and not the other, so 64 bit integers
could easily be mixed-endian on many current architectures.


Show us one concrete example.

C implementors are usually not the most stupid people around and they
understand quite well the need for a consistent byte order among all the
types.

All the realistic examples of mixed endianness are historical, from an
age where the byte order issues were not as well understood as they have
been for the last quarter of century.


Here are two examples illustrating Christian's exact point:

The ARM SDT toolset (1996-2001?) had long long numbers stored with the least
significant word first, even when the ARM was in big-endian mode, although
this was changed in the ARM ADS toolset.

The ARM FP instruction set provides IEEE single, double and 80-bit extended
double formats, but these are stored most significant word first, even on an
ARM in little-endian mode.

Another "historical", but still current example: many PC graphics cards
provide 4bpp modes where the pixel nibbles are packed big-endian within
bytes, but the bytes are packed little-endian within words.

--
Kevin Bracey
http://www.bracey-griffith.freeserve.co.uk/
Nov 14 '05 #61
Arthur J. O'Dwyer wrote:
I think you're right; but I don't understand why the asymmetry
here. Why does the Standard allow '*P' but not 'P[0]'? (It's
obvious enough why it doesn't allow 'P[foo]', but I would have
extended that to make '*P' invalid, rather than making a seemingly
arbitrary distinction between the two indirection operators.)


The distinction is not entirely arbitrary: 'P[0]' is disallowed
because of the pointer arithmetic, not the indirection. Pointer
arithmetic /must/ be disallowed on incomplete types in general,
because the size of the referenced type is not known; making a special
exception to allow P[0] /would/ be arbitrary, especially since the
value of the subscript is not generally known at compile time.

Still, I consider it a flaw in the standard that no constraint
disallows indirection on pointers to incomplete types.

Jeremy.
Nov 14 '05 #62
In <40***********@mindspring.com> pete <pf*****@mindspring.com> writes:
Dan Pop wrote:

In <c0*********@enews2.newsguy.com>
Chris Torek <no****@torek.net> writes:
>[on "PDP-endian"-ness] >>There are exactly two byte orders that have survived and, by no
>>coincidence, they are the two entirely consistent ones.
>
>I am willing to bet that at least one CPU architecture will resurrect
>mixed-endian integers in its 32-to-64-bit transition. (I suspect
>it will be an existing little-endian architecture that is heavily
>stack-oriented, too.)


Which one would be that?


In the context of this newsgroup, I don't think it's worthwhile
to memorize a subset of the allowable configurations,
which are extant today. I don't even think it's valid to claim
that you know all the extant ones.


Even in the context of this newsgroup, it makes sense to distinguish
between realistically portable code and absolutely portable code.

If absolute portability comes at a cost, it's worth evaluating this cost
before choosing between a realistically portable solution and an
absolutely portable one. And this is usually the case when dealing with
byte order issues: if accomodating *any* byte order is too expensive in
terms of code complexity/performance, by restricting yourself to the
two popular byte orders you're portable to practically any hosted
implementation in current use.

Portability *exclusively* for portability's sake is a form of religion
few competent professionals are willing to embrace. YMMV.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #63
Da*****@cern.ch (Dan Pop) writes:
[...]
If absolute portability comes at a cost, it's worth evaluating this cost
before choosing between a realistically portable solution and an
absolutely portable one. And this is usually the case when dealing with
byte order issues: if accomodating *any* byte order is too expensive in
terms of code complexity/performance, by restricting yourself to the
two popular byte orders you're portable to practically any hosted
implementation in current use.

[...]

Agreed. It's best to write code that doesn't care about byte order,
but of course that's not always possible.

Once you've made a decision to limit the portability of your program,
it's often a good idea to have an explicit check that your assumptions
aren't violated. It's always possible that someone might try to
compile and run your code on some exotic system with middle-endian
byte order or 13-bit bytes.

If you can check your assumptions at compile time, you can prevent the
program from compiling in the first place; for example:

#include <limits.h>

#if CHAR_BIT != 8
#error "This program is supported only on systems with 8-bit bytes."
#endif

... Code that assumes 8-bit bytes ...

If that's not possible, you can include a function that aborts the
program if your conditions are not met, and call it once at program
startup.

(Of course, you also have to decide whether this is worth the effort.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
Nov 14 '05 #64
In <ln************@nuthaus.mib.org> Keith Thompson <ks***@mib.org> writes:
Da*****@cern.ch (Dan Pop) writes:
[...]
If absolute portability comes at a cost, it's worth evaluating this cost
before choosing between a realistically portable solution and an
absolutely portable one. And this is usually the case when dealing with
byte order issues: if accomodating *any* byte order is too expensive in
terms of code complexity/performance, by restricting yourself to the
two popular byte orders you're portable to practically any hosted
implementation in current use.

[...]

Agreed. It's best to write code that doesn't care about byte order,
but of course that's not always possible.

Once you've made a decision to limit the portability of your program,
it's often a good idea to have an explicit check that your assumptions
aren't violated. It's always possible that someone might try to
compile and run your code on some exotic system with middle-endian
byte order or 13-bit bytes.

If you can check your assumptions at compile time, you can prevent the
program from compiling in the first place; for example:

#include <limits.h>

#if CHAR_BIT != 8
#error "This program is supported only on systems with 8-bit bytes."
#endif

... Code that assumes 8-bit bytes ...

If that's not possible, you can include a function that aborts the
program if your conditions are not met, and call it once at program
startup.

(Of course, you also have to decide whether this is worth the effort.)


And regardless of what you decide, you have to also document the fact
that the code relies on a particular set of assumptions. This way, you
can save the trouble of building and executing the program only to
discover (one way or another) that it doesn't work on that implementation.

There are still people who read the quick start documentation *before*
trying anything else ;-)

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #65
Dan Pop wrote:
CBFalconer <cb********@yahoo.com> writes:
Dan Pop wrote:
CBFalconer <cb********@yahoo.com> writes:
>Papadopoulos Giannis wrote:
>> Mantorok Redgormor wrote:
>>
>> > #include <stdio.h>
>> > struct foo { int example; struct bar *ptr; };
>> >
>> > int main(void)
>> > {
>> > struct foo baz;
>> > baz.ptr = NULL; /* Undefined behavior? */
>> > return 0;
>> > }
>>
>> first of all define struct bar nad #include <stdlib.h>
>
> Why should he? That is a serious question. He doesn't need
> stdio.h either.

Then, where is NULL defined? Have I ever recommended engaging
the brain before posting? ;-)


Cavil: I didn't say he didn't have to compensate.


If he had to compensate, then stdio.h *was needed*.


At least two possible options, including:

#include <stddef.h>
#define NULL (void *)0

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #66
In <40***************@yahoo.com> CBFalconer <cb********@yahoo.com> writes:
Dan Pop wrote:
CBFalconer <cb********@yahoo.com> writes:
>Dan Pop wrote:
>> CBFalconer <cb********@yahoo.com> writes:
>> >Papadopoulos Giannis wrote:
>> >> Mantorok Redgormor wrote:
>> >>
>> >> > #include <stdio.h>
>> >> > struct foo { int example; struct bar *ptr; };
>> >> >
>> >> > int main(void)
>> >> > {
>> >> > struct foo baz;
>> >> > baz.ptr = NULL; /* Undefined behavior? */
>> >> > return 0;
>> >> > }
>> >>
>> >> first of all define struct bar nad #include <stdlib.h>
>> >
>> > Why should he? That is a serious question. He doesn't need
>> > stdio.h either.
>>
>> Then, where is NULL defined? Have I ever recommended engaging
>> the brain before posting? ;-)
>
>Cavil: I didn't say he didn't have to compensate.


If he had to compensate, then stdio.h *was needed*.


At least two possible options, including:

#include <stddef.h>
#define NULL (void *)0


But, since he didn't use any of these, including <stdio.h> *was needed*.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #67

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: Joona I Palaste | last post by:
We all know that this: void *p; if (p=malloc(1)) { free(p); p; } causes undefined behaviour if malloc() succeeds. But what about this?
19
by: E. Robert Tisdale | last post by:
In the context of the comp.lang.c newsgroup, the term "undefined behavior" actually refers to behavior not defined by the ANSI/ISO C 9 standard. Specifically, it is *not* true that "anything can...
25
by: Nitin Bhardwaj | last post by:
Well, i'm a relatively new into C( strictly speaking : well i'm a student and have been doing & studying C programming for the last 4 years).....and also a regular reader of "comp.lang.c" I...
16
by: Jim Langston | last post by:
I know that functions starting with an underscore, or two underscores, are reserved by the compiler/c++ and should not be used by the user and may cause undefined behavior. My question is, how...
33
by: dragoncoder | last post by:
Hi all, Does the following code invoke undefined behaviour ? $ cat a1.cc #include <iostream> #include <limits> int main() { int a = INT_MAX/2;
12
by: Rajesh S R | last post by:
Can anyone tell me what is the difference between undefined behavior and unspecified behavior? Though I've read what is given about them, in ISO standards, I'm still not able to get the...
7
by: thamizh.veriyan | last post by:
Hi, I am new to this community. I have a doubt regarding trap representations. I read in IBM's website that something like this is legal: int main(){ int x=3; {
12
by: Franz Hose | last post by:
the following program, when compiled with gcc and '-std=c99', gcc says test.c:6: error: jump into scope of identifier with variably modified type that is, it does not even compile. ...
33
by: coolguyaroundyou | last post by:
Will the following statement invoke undefined behavior : a^=b,b^=a,a^=b ; given that a and b are of int-type ?? Be cautious, I have not written a^=b^=a^=b ; which, of course, is undefined....
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.