Qry : Behaviour of fgets -- ?

R

Richard Bos

Harald van =?UTF-8?B?RMSzaw==?= said:
I didn't say "the laws of physics as discovered (so far)", I copied Bart van
Ingen Schenau's unqualified "the laws of physics", which do exist even if
we don't fully know them yet.

You don't know that. You may think you do, but you don't - because
nobody does. What's more, what we do know is that at least some of the
laws that do seem to exist have a random factor in them.
And regardless of whether you want to make
that distinction, I doubt you honestly believe anyone's neighbour turned
into a piano. Some more context:

"The standard does indeed not require that UB causes my next door
neighbour to turn into a piano, but that appears to be exactly the
behaviour of my DeathStation 9000.
Are you claiming that this behaviour is not correct?" - Bart v Ingen Schenau

According to quantum physics, it is highly unlikely, but _not_
impossible, for all of his neighbour's constituting quantum particles to
suddenly collapse into a state which happens to result in a piano. It is
indeed even less likely that such an occurrence would happen just as
Bart writes through an undefined pointer on his DS9K, but again, not
impossible. Whether such a contemporality implies a causality or is only
synchronous is a question only Carl and Kaz can answer.

Richard
 
D

David Spencer

So that they can work wothout FILE being a complete type. You said it
had to be one so that getc() and putc() could be macros; but that's not true
because the definition of getc() could cast the FILE * to, say, _FILE *,
where _FILE is the complete type.

The implementor knows the offsets of the structure members. His getc
could cast the FILE * to unsigned char *, add the offset and cast to
the member's type. That's effectively what his compiler is going to
do in any case. But again, the library function need not be in C, so
the implementor doesn't have to use C hackery to get the right result.
The internal structure of a FILE is necessarily
implementation-dependent, so there's no reason any FILE function
should be ISO C.

As someone else pointed out, an implementor can't hide a structure
from a sufficiently perverse and determined programmer with a
decompiler. But that's true of any opaque type; it doesn't affect the
usefulness of opacity.
 
A

Army1987

That's a bold claim. With fgets, it would work on my implementation. With
strlen for example, it would not, because <string.h>'s macro definition of
strcpy refers to it by name. Are you sure no implementation does anything
similar with fgets?
Just curious, how does it define strcpy in terms of strlen while
evaluating each argument exactly once?
 
C

CBFalconer

Richard said:
So that they can work wothout FILE being a complete type. You
said it had to be one so that getc() and putc() could be macros;
but that's not true because the definition of getc() could cast
the FILE * to, say, _FILE *, where _FILE is the complete type.

But the only point of the macros is to access the internal
structure of the FILE object for such items as buffer usage
counters, etc. It also has to be able to call some routine to
refill the buffers when exhausted. The point of the macro is not
to have a macro, but to increase the system performance level.
_FILE knows nothing about these, and is thus useless.

Please don't strip attributions (the "Joe wrote" initial lines) for
any material you quote.
 
R

Richard Tobin

So that they can work wothout FILE being a complete type. You
said it had to be one so that getc() and putc() could be macros;
but that's not true because the definition of getc() could cast
the FILE * to, say, _FILE *, where _FILE is the complete type.
[/QUOTE]
But the only point of the macros is to access the internal
structure of the FILE object for such items as buffer usage
counters, etc. It also has to be able to call some routine to
refill the buffers when exhausted. The point of the macro is not
to have a macro, but to increase the system performance level.
_FILE knows nothing about these, and is thus useless.

_FILE would contain the real fields.

This is getting tedious, so here's a sketch of an extract from stdio.h:

typedef struct FILE FILE;

typedef struct _FILE {
unsigned char *buf;
insigned char *pos;
int count;
...
} _FILE;

#define getc(f) (((_FILE *)(f))->count-- > 0 ?
(int)*((_FILE *)(f))->pos++ :
getc(f))

It's just like it would be if FILE was the complete type, but with
casts to _FILE * everywhere.

-- Richard
 
W

Wojtek Lerch

CBFalconer said:
But the only point of the macros is to access the internal
structure of the FILE object for such items as buffer usage
counters, etc. It also has to be able to call some routine to
refill the buffers when exhausted. The point of the macro is not
to have a macro, but to increase the system performance level.
_FILE knows nothing about these, and is thus useless.

The original argument was whether it's necessary for FILE to be a complete
type for putc and gets to be implemented as macros. The counterargument was
that it's not, because it's possible for the macros to use a different,
complete type. It wasn't about whether it's useful or practical, it was
about whether it's possible.

Whether it's practical is another story. I can think of an example where
FILE is the whole structure and is only defined as a complete type in the
implementor's private header, and _FILE is a smaller structure that contains
ony those members that are needed by the macros. For instance:

In <stdio.h>:

typedef struct _BIGFILE FILE;
typedef struct _SMALLFILE {
char *ptr, *end;
} _FILE;

#define getc( fp ) ( ((_FILE*)(fp)) -> ptr != ((_FILE*)(fp)) -> end ?
*((_FILE*)(fp))->ptr++ : _Getc(fp) )

In the library:

struct _BIGFILE {
_FILE header;
// More stuff here
};

Of course, it might make even more sense for the implementor to define FILE
to be the small structure and make the big structure a completely private
type in the library, but that is largely a matter of taste.
 
?

=?iso-2022-kr?q?Harald_van_D=0E=29=26=0Fk?=

Just curious, how does it define strcpy in terms of strlen while
evaluating each argument exactly once?

By only using the execution path that calls strlen when the argument is a
constant. The as-if rule allows the argument to be evaluated multiple
times, so long as a correct program cannot tell the difference.
Reformatted a bit for readabiliy, it looks like this:

#define strcpy(dest, src) \
(__extension__ (__builtin_constant_p (src) \
? (__string2_1bptr_p (src) \
&& strlen (src) + 1 <= 8 \
? __strcpy_small (dest, \
__strcpy_args (src), \
strlen (src) + 1) \
: (char *) memcpy (dest, src, \
strlen (src) + 1)) \
: strcpy (dest, src)))
 
K

Keith Thompson

Rainer Weikusat said:
This text would fit into a newsgroup whose topic is production of
mildly creative absurd fiction or one discussing quirks of a
particular implementation of C BUT NOT into a discussion of C, because
it is only insofar related to it as it talks about something the
C-standard does not talk about. And 'C' is the set of things the
C-standard DOES talk about.

One would assume that this cannot be that complicated for someone
trying to understand it, ie someone whose motivation is not the very
production of mildly creative absurd fiction.

We're talking about things that the C standard *explicitly* declines
to talk about. The motivation of these specific (admittedly absurd)
examples is to illuminate just what "undefined behavior" means.

Too many newbies assume that
int i = 3;
i = i++;
can only set i to 3 or to 4, and cannot possibly have any other
effect. Saying that this code may instead print "a suffusion of
yellow" in a conforming implementation is a statement about C, and it
illustrates something that's very important for C programmers to
understand.

If you dislike the "nasal demons" metaphor, that's fine, but there is
a real point to it; we're not just messing around.
 
K

Keith Thompson

You can't prevent perverse programmers from doing anything. They're
too determined. If getc() can see the internals, so can anyone with
sufficiently poor taste.

Right, and the price they pay is that their code breaks when ported to
another implementation, or when the declaration of FILE changes.
I think the advantage of making FILE an incomplete type would be more
to prevent inexperienced programmers from making mistakes about what
is legal, such as trying to copy a FILE object (which may or may not
work depending on the implementation).

Exactly.
 
K

Keith Thompson

Army1987 said:
No, they don't. Nature has no laws. Nature has behaviour. We observe
that behaviour, and formulate "laws" which explain it. Nature, however,
is under no obligation to observe those "laws" (and indeed frequently
breaks them). For example, the vast majority of gases don't observe the
gas laws.

<topicality level="LDBL_MIN">
They are approximate laws. There are laws which instead are
believed to be exact (e.g. the conservation of electrical charge).
So even if the Standard doesn't forbid

char *str = "Hey!";
size_t len = strlen(str);
struct flexible {
size_t size;
char data[1];
} *word = malloc(sizeof *word + len);
if (word != NULL) {
word->size = len;
strcpy(word->data, str);
puts(word->data);
}

from causing all electrons in my body to turn into positrons, I
am quite confident that this won't happen.

All the electrons in your body could turn into positrons without
violating the conservation of electrical charge, as long as an
appropriate number of negatively charged particles are also created.

Fewer things are impossible than you might assume.
 
K

Kenneth Brody

Rainer said:
This text would fit into a newsgroup whose topic is production of
mildly creative absurd fiction or one discussing quirks of a
particular implementation of C BUT NOT into a discussion of C, because
it is only insofar related to it as it talks about something the
C-standard does not talk about. And 'C' is the set of things the
C-standard DOES talk about.

We're talking about "undefined behavior", which is something that
the Standard purposely leaves _undefined_. This means that _any_
behavior is acceptable as far as the Standard is concerned.

This is not the case of a "quick of a particular implementation".
Rather, it is a specific counterexample to the false assertion
that "i = i++;" can only do one of two things -- leave "i" alone,
or increment it.
One would assume that this cannot be that complicated for someone
trying to understand it, ie someone whose motivation is not the very
production of mildly creative absurd fiction.

What is so complicated about understanding that these are used to
show that those false assertions above are, in fact, false? And, as
such, serve a very real purpose?

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
A

Army1987

All the electrons in your body could turn into positrons without
violating the conservation of electrical charge, as long as an
appropriate number of negatively charged particles are also created.

Fewer things are impossible than you might assume.
Should've said "...without creating any other negatively charged
particle". However, I acknowledge that the scenario you describe
would be scary enough regardless of where those particles are
created.
 
K

kuyper

Rainer Weikusat wrote:
....
This text would fit into a newsgroup whose topic is production of
mildly creative absurd fiction or one discussing quirks of a
particular implementation of C BUT NOT into a discussion of C, because
it is only insofar related to it as it talks about something the
C-standard does not talk about. And 'C' is the set of things the
C-standard DOES talk about.

It is perfectly on-topic to talk about what freedoms the standard
allows, just as much as it is on-topic to talk about what restrictions
it imposes. It is pointless to go into great details about the freedom
the standard allows when the behavior is undefined. But it is NOT
pointless to illustrute what "undefined behavior" means by giving
extreme examples.
 
M

Mark McIntyre

All the electrons in your body could turn into positrons without
violating the conservation of electrical charge,

Quite likely to violate conservation of mass, energy and momentum
tho...
as long as an
appropriate number of negatively charged particles are also created.

Fewer things are impossible than you might assume.

Technically, nothing is impossible since the universe is infinite in
some dimension or other.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
C

Charlie Gordon

Keith Thompson said:
Army1987 said:
No, they don't. Nature has no laws. Nature has behaviour. We observe
that behaviour, and formulate "laws" which explain it. Nature, however,
is under no obligation to observe those "laws" (and indeed frequently
breaks them). For example, the vast majority of gases don't observe the
gas laws.

<topicality level="LDBL_MIN">
They are approximate laws. There are laws which instead are
believed to be exact (e.g. the conservation of electrical charge).
So even if the Standard doesn't forbid

char *str = "Hey!";
size_t len = strlen(str);
struct flexible {
size_t size;
char data[1];
} *word = malloc(sizeof *word + len);
if (word != NULL) {
word->size = len;
strcpy(word->data, str);
puts(word->data);
}

from causing all electrons in my body to turn into positrons, I
am quite confident that this won't happen.

All the electrons in your body could turn into positrons without
violating the conservation of electrical charge, as long as an
appropriate number of negatively charged particles are also created.

Such as all protons in his body turning into antiprotons... Not a good time
to shake hands !
 
C

Charlie Gordon

Mark McIntyre said:
Quite likely to violate conservation of mass, energy and momentum
tho...


Technically, nothing is impossible since the universe is infinite in
some dimension or other.

I'm afraid that's impossible to prove.
 
C

CBFalconer

Richard said:
_FILE would contain the real fields.

This is getting tedious, so here's a sketch of an extract from
stdio.h:

typedef struct FILE FILE;

typedef struct _FILE {
unsigned char *buf;
insigned char *pos;
int count;
...
} _FILE;

#define getc(f) (((_FILE *)(f))->count-- > 0 ?
(int)*((_FILE *)(f))->pos++ :
getc(f))

It's just like it would be if FILE was the complete type, but
with casts to _FILE * everywhere.

And what makes you think that that _FILE description describes the
actual structure that exists for any arbitrary file? If it does,
it may well work. If not, it certainly won't.

However, the system implementor can limit the information he
publishes by:

#define getc(f) ((f)->count-- > 0 ? *((f)->pos++) : (getc(f))

#define _FILEbuf .... /* the things used in getc or putc */

typedef struct FILE {_FILEbuf, _FILEstuff}

so that a pointer to a FILE is also a pointer to a _FILEbuf, but
the knowledge exposed is limited. Don't worry about syntax errors
above, I am just trying to pass on the general idea. The
definitions for _FILEstuff are elsewhere, and never user
accessible.

BTW, you have again deleted attributions for material you quoted.
Don't do that, some people also get highly annoyed at having their
words stolen without attribution.
 
G

Giorgos Keramidas

No they don't, except when they are in the function *definition*. In
a mere declaration, adding the restrict qualifier to parameters is as
meaningless as adding the const qualifier.

Hmmm... Doesn't that "break" the whole concept of 'restrict' as a
qualifier for separate translation units?
The following program is strictly conforming:

void fun( int *restrict p, int *restrict q );

int main( void ) {
int a = 0;
fun( &a, &a );
return a;
}

void fun( int *const x, int *const y ) {
*x = *y + 1;
*y = *x - 1;
}

What happens when the function definition of fun() is in an entirely
separate TU? Isn't than the 'restrict' qualifier useful in the header
file of that TU?
 
R

Rainer Weikusat

kuyper said:
Rainer said:
This text would fit into a newsgroup whose topic is production of
mildly creative absurd fiction or one discussing quirks of a
particular implementation of C BUT NOT into a discussion of C, because
it is only insofar related to it as it talks about something the
C-standard does not talk about. And 'C' is the set of things the
C-standard DOES talk about.
[...]

But it is NOT pointless to illustrute what "undefined behavior"
means by giving extreme examples.

It is not possible to illustrate 'nothing' by providing examples of
it.
 
R

Richard Tobin

This is getting tedious, so here's a sketch of an extract from
stdio.h:

typedef struct FILE FILE;

typedef struct _FILE {
unsigned char *buf;
insigned char *pos;
int count;
...
} _FILE;

#define getc(f) (((_FILE *)(f))->count-- > 0 ?
(int)*((_FILE *)(f))->pos++ :
getc(f))

It's just like it would be if FILE was the complete type, but
with casts to _FILE * everywhere.
[/QUOTE]
And what makes you think that that _FILE description describes the
actual structure that exists for any arbitrary file? If it does,
it may well work. If not, it certainly won't.

I'm describing a possible implementation. _FILE contains the correct
structure because the implementor decided it that way.

-- Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,102
Messages
2,570,645
Members
47,244
Latest member
OdessaH562

Latest Threads

Top