Qry : Behaviour of fgets -- ?

B

Ben Bacarisse

Army1987 said:
[...]To find out
which we use strchr searching for '\0' which will always succeed. If the
NUL is at buff[size-1] we assume the line is longer than buff.

Doesn't strlen(buf) != size - 1 do the same without looking that
weird?
Or better, set buff[size - 1] to a nonzero value, call fgets, and
check whether buff[size - 1] is zero. This takes O(1) time.

This is a neat solution because it also works in the peculiar case of
a line with embedded nulls.
 
B

Ben Bacarisse

CBFalconer said:
Keith Thompson wrote:
Generating such a file is a non-trivial exercise, as I discovered
when I created some long lines for ggets testing in the first
place.

Off topic (in c.l.c), but

tr -d '\n' </usr/dict/words

is hardly complex. Indeed, the above with any import will make one
long line.
 
J

Justin.SpahrSummers

I guess that this mean that
printf("%p\n", (void *)0);
causes UB... Is this intended or is it just a glitch in the
Standard?

That's an interesting question... I can't find anything in 7.19.6
proper or 7.19.6.1 that contradicts 7.1.4 explicitly; however, there
is wording in the form of "The value of the pointer is converted to a
sequence of printing characters, in an implementation-defined manner."
Since NULL is still a possible value of a pointer, one could infer
that it would still be printed out in an "implementation-defined
manner," but, of course, this is rather ambiguous.
 
C

Charlie Gordon

Keith Thompson said:
Chris Dollin said:
jacob navia wrote: [...]
In the case of fgets this implies:
o Testing for NULL.
o Testing for a bad value of n (<= 0)
o Testing for a NULL value in the receiving buffer.
[...]

o Testing that the non-null buffer points to a legal C object
containing at least the `n` characters required

o Testing that the non-null stream points to a legal C object

Of course these last two may be impossible to check unless the
implementation keep track of *all* objects, which would impose a
tremendous overhead.

Only the char * pointer would be hard to verify, the stream pointer should
be easy to check against open streams handled by the library, as any
conforming library needs to account for at least those open for write and
update:

7.19.5.2p3 If stream is a null pointer, the fflush function performs this
flushing action on all
streams for which the behavior is defined above.

C libraries used to allocate FILE structures from a static array: checking
for valid FILE pointers was pretty easy then. I would be surprised if
current implementations could no longer do this efficiently.

Chqrlie.
 
R

Richard Heathfield

Army1987 said:
[Removed comp.unix.programmer and added comp.std.c in the
newsgroups list]

Section 7.1.4 paragraph 1 of the C language standard makes it quite
clear that passing a null pointer to a function that does not
document accepting a null pointer is undefined behavior.

I guess that this mean that
printf("%p\n", (void *)0);
causes UB... Is this intended or is it just a glitch in the
Standard?

The committee certainly had no intent to disallow passing a null pointer
to (f)printf, as one of them (Doug Gwyn) made abundantly clear in a
recent thread (it was a year or three ago, but that's still recent,
right?).

Whether the Standard /actually/ disallows passing a null pointer to
(f)printf is another matter, and one that I am not convinced was ever
actually resolved.
 
C

Charlie Gordon

Keith Thompson said:
Here's the declaration of fgets:

char *fgets(char * restrict s, int n, FILE * restrict stream);

This has probably been discussed before, but I couldn't find a relevant
reference.

Why do we have restrict keywords on s and stream in this function prototype?
They seem to convey no useful information here.

Can anyone explain ?
 
R

Richard Heathfield

Charlie Gordon said:
This has probably been discussed before, but I couldn't find a
relevant reference.

Why do we have restrict keywords on s and stream in this function
prototype? They seem to convey no useful information here.

Can anyone explain ?

Probably misplaced zeal. The Rationale explains that it's to promise the
compiler that s and stream are not aliaseseseses of each other. Um,
yes, okay, er... fine.
 
D

Douglas A. Gwyn

Army1987 said:
You're not allowed to do that.

Not allowed by whom? The program may not be strictly conforming,
but it should still work. If you want to get really fussy about it, make
"mystdio.h" define FILE without including <stdio.h> (which requires
some implementation-dependent kludgery); then the fgets-redefining
macro is "allowed".
stdio.h defines size_t, too.

Thanks. The redundant header <stddef.h> could be omitted,
although it didn't hurt to include it.
 
C

CBFalconer

Charlie said:
This has probably been discussed before, but I couldn't find a
relevant reference. Why do we have restrict keywords on s and
stream in this function prototype? They seem to convey no useful
information here. Can anyone explain ?

They certainly do convey useful information. They advise the
compiler of the fgets software that using *stream will not affect
*s, and vice-versa. This enables more extensive optimization, and
thus faster code.
 
C

CBFalconer

Douglas A. Gwyn said:
Not allowed by whom? The program may not be strictly conforming,
but it should still work. If you want to get really fussy about
it, make "mystdio.h" define FILE without including <stdio.h>
(which requires some implementation-dependent kludgery); then the
fgets-redefining macro is "allowed".

Not allowed by the C standard. Just because it will work on _some_
systems doesn't make it viable. Undefined behaviour includes doing
what you think is right.
 
C

CBFalconer

Richard said:
Army1987 said:

The committee certainly had no intent to disallow passing a null
pointer to (f)printf, as one of them (Doug Gwyn) made abundantly
clear in a recent thread (it was a year or three ago, but that's
still recent, right?).

Whether the Standard /actually/ disallows passing a null pointer
to (f)printf is another matter, and one that I am not convinced
was ever actually resolved.

Lets make clear that this discussion deals only with NULLs that are
accessed via the %p format specification. Note that this has to be
reversible via the scanf mechanism. The non-standard practice
(implemented by some GNU libraries) of printing (NULL) for all
NULLs should satisfy all comers.
 
R

Rainer Weikusat

Keith Thompson said:
Rainer Weikusat said:
Jonathan Leffler said:
Rainer Weikusat wrote: [...]
Any statement ascribing properties to areas not defined by the
C-standard is a statement about something which is not part of C, as
defined by this standard.

Read up on 'Nasal Demons' (Google - 4th entry when I looked). In
comp.std.c land, undefined behaviour means exactly that.

Well, I wasn't about writing 'preferred phantasies of comp.std.c
regulars' but about C. And from the perpsective of the standard text,
claiming that

a = 3;
a = ++a;

results in any particular value for a is as wrong as claiming that it
may cause your next door neighbour to turn into a piano. If it may can
be determined empirically and both the answer and the means for
determining it are not part of the C programming language.

We don't claim (except jokingly) that executing those statements
*will* cause demons to fly out of your nose. The claim is merely that
nasal demons are one of the infinitely many behaviors permitted by the
standard.

It is one of the infinitely many things humans make up because
something like an inbred horror vacui compels them to fill any void
with something. But any example of "behaviour" is necessarily
defined and not undefined.
 
R

Rainer Weikusat

Bart van Ingen Schenau said:
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?

I claim that this behaviour is highly illegal and would suggest that
you should try to get a different computer. Apart from that, since no
(standard) definition of 'correct behaviour' exists for this
particular case, its 'correctness' cannot be argued about without
refering to some definition of 'correct behaviour' which is not the
C-standard.
 
C

Casper H.S. Dik

Ben Bacarisse said:
]To find out
which we use strchr searching for '\0' which will always succeed. If the
NUL is at buff[size-1] we assume the line is longer than buff.

Doesn't strlen(buf) != size - 1 do the same without looking that
weird?
Or better, set buff[size - 1] to a nonzero value, call fgets, and
check whether buff[size - 1] is zero. This takes O(1) time.
This is a neat solution because it also works in the peculiar case of
a line with embedded nulls.


But does the standard restrict writes to the part of the buffer
where no data was read, i.e., is a standard conforming
implementation allowed to start fgets with:

memset(s, '\0', n);
....


Casper
 
R

Richard Bos

Rainer Weikusat said:
It is one of the infinitely many things humans make up because
something like an inbred horror vacui compels them to fill any void
with something. But any example of "behaviour" is necessarily
defined and not undefined.

You have obviously never read much about quantum physics. And yes, when
the Standard does not define what a piece of code does but leaves it up
to the compiler, and when that compiler does not care to make sure that
that code does something specific but leaves it up to the accidents of
microprocessor behaviour (which both could very well do, and with good
reason), then quantum physics really can toss the coin about how that
code behaves, on that day, on that computer.

Richard
 
C

Chris Dollin

Rainer said:
It is one of the infinitely many things humans make up because
something like an inbred horror vacui compels them to fill any void
with something. But any example of "behaviour" is necessarily
defined and not undefined.

(a) There are many instances of behaviour not defined /by the C standard/,
which is the backdrop to our usage here.

(b) There are many instances of behaviour that are not /defined/ at all;
just look out of your window.
 
R

Rainer Weikusat

You have obviously never read much about quantum physics.

You have obviously some trouble in understanding to concept of
'abstractly defined semantic'. Since they are a) abstract and b)
exist-only-as-defined, whatever you believe to not know about physics
simply does not apply here.
And yes, when the Standard does not define what a piece of code does

Then the standard does not define what a piece of code does. And
that's the end of it in this respect. But fwiw,
but leaves it up to the compiler, and when that compiler does not
care to make sure that that code does something specific but leaves
it up to the accidents of microprocessor behaviour

It is not (generally) possible to execute microprocessor instructions
which don't do something specific. But this speculation is besides the
point. The bheaviours is undefined. This means it is undefined.
 
K

Keith Thompson

Rainer Weikusat said:
It is one of the infinitely many things humans make up because
something like an inbred horror vacui compels them to fill any void
with something. But any example of "behaviour" is necessarily
defined and not undefined.

The behavior is not defined *by the standard*. If it happens to be
defined by something else, that's fine, but it's not relevant here in
comp.{lang,std}.c.
 
R

Rainer Weikusat

Chris Dollin said:
(a) There are many instances of behaviour not defined /by the C standard/,
which is the backdrop to our usage here.

Put straight into context: There are many instance of beahviour not
defined by the C standard, and since you are claiming to discuss the
C-standard, you spend an enourmous amount of typing to publish wild
speculations about things not defined by the C-standard?

Does that sound a little contradictory? What's YOUR problem with
accepting that what isn't there simply isn't there?

And could you perhaps discuss this with a professional?
 
R

Rainer Weikusat

Keith Thompson said:
The behavior is not defined *by the standard*. If it happens to be
defined by something else, that's fine, but it's not relevant here in
comp.{lang,std}.c.

You misunderstand my point. To state that 'the behavious is undefined'
means 'no information regarding this behaviour is available'. This
makes (as I have already written) the claim that 'anything can happen'
as wrong as the claim that 'it will cause global warming to stop' or
'nothing will happen' or 'it will cause a to be incremented twice' or
any other conceivable description of any something. The defined
reality of this place is void and any discussion going beyond stating
the the behaviour of ... is undefined is a discussion about something
which is not part of the C programming language as defined by the
C-standard.

As soon as you (or anyvbody else) claims that such-and-such a thing
may happen, you are not talking about C anymore.
 

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,091
Messages
2,570,605
Members
47,225
Latest member
DarrinWhit

Latest Threads

Top