pointer to const int

C

CBFalconer

Keith said:
.... snip ...


It *may* cause undefined behavior, depending on a particular
implementation-defined choice. (I didn't take the time to word
my claim more carefully; it was meant to be a throwaway line.)

C99 7.19.2p2:

A text stream is an ordered sequence of characters composed into
_lines_, each line consisting of zero or more characters plus a
terminating new-line character Whether the last line requires a
terminating new-line character is implementation-defined.

If an implementation requires the terminating new-line character,
what happens if a program doesn't provide it? The standard
doesn't say, so the behavior is undefined by omission.

Similarly, if the standard says that "system may or may not return
a signal on program execution", or equivalent, then executing
'system' and relying on such behaviour runs into the same
provision. I.e. the lack of definition means the action is
undefined. I don't consider any other reaction to be consistent.
 
J

Jun Woong

Harald van Dijk said:
Keith Thompson said:
[...]
I argue that this:
int main() { /* ... */ }
is *not* equivalent to this:
int main(void) { /* ... */ }
[...]
Probably adding the wording for "int main()" to the normative text or to
the footnote 9 (I'm using N1256) seems to be necessary to clarify the
intent.

This would allow

int main(argc, argv, envp)
int argc;
char **argv;
char **envp;
{}

because the defined type is int main().

No, it would not. The standard already has the wording to restrict
the number of parameters:

N1256 5.1.2.2.1p1:
It shall be defined with a return type of int and with no
parameters: [...]
What if "It shall be defined with [...]" were changed to "It shall be
(defined as) compatible with [...]"? This, I believe, allows old-style
definitions that actually define main with 0 or 2 parameters of the
appropriate type, without allowing other old-style definitions.

Sounds good. Or removing the code snippet entirely and make the
requirement prose. I think the code snippet is a hangover and don't
think it is really necessary.
 
J

Jun Woong

Keith Thompson said:
Probably adding the wording for "int main()" to the normative text or
to the footnote 9 (I'm using N1256) seems to be necessary to clarify
the intent.

Adding such wording to the normative text, so there are three valid cases:

int main(void) { /* ... */ }
int main() { /* ... */ }
int main(int argc, char *argv[]) { /* ... */ }

If we add "int main() { ... }" no reason to exclude the non-prototype
form for the last one.
would certainly solve the problem (assuming that it is a problem).
Adding such wording to a non-normative footnote would clarify the
intent, but it would contradict the normative text; "int main()" would
still fail to be equivalent to "int main(void)".

This discussion would be moot if the C1X committee has a plan to
completely remove non-prototype forms from the next version. So under
the assumption that they will not be dropped and that the committee
HAS an interest to handle a problem about non-prototypes (see what
happened to DR255 that I proposed in csc.), I think one can take
those corresponding non-prototype definitions as "equivalent;" The
standard already says "equivalent" for those having a subtle
difference with adding a footnote to explain the difference:

N1256 5.1.2.2.3p1:
If the return type of the main function is a type compatible with
int, a return from the initial call to the main function is
equivalent to calling the exit function with the value returned by
the main function as its argument
 
E

Eric Sosman

CBFalconer said:
If you look at the source code for ggets you will see that a final
line without a '\n' termination is automatically treated the same
as a line with a '\n' termination. This is tied into the
absorption of the '\n' terminating all lines.

FWIW, I took the opposite approach in my getline().
The principle I followed was "Don't dick with the data,"
so the presence or absence of a '\n' (as delivered by the
C library) is faithfully reported to the getline() caller
to note or disregard as appropriate. "It's not the job of
a low-level function," quoth I, "to make policy decisions
on behalf of its callers."
 
K

Keith Thompson

CBFalconer said:
If you look at the source code for ggets you will see that a final
line without a '\n' termination is automatically treated the same
as a line with a '\n' termination. This is tied into the
absorption of the '\n' terminating all lines.

Which means that, even on systems that don't require a trailing
new-line, you can't distinguish between a text file that has a
trailing new-line and one that doesn't. Some might consider that a
disadvantage.
 
K

Keith Thompson

CBFalconer said:
Similarly, if the standard says that "system may or may not return
a signal on program execution", or equivalent, then executing
'system' and relying on such behaviour runs into the same
provision. I.e. the lack of definition means the action is
undefined. I don't consider any other reaction to be consistent.

But it's important to note that "Whether the last line requires a
terminating new-line character is *implementation-defined*" (emphasis
added), which means that the implementation is required to document
its choice. Thus code that assumes the new-line is not required does
*not* invoke UB when executed on a system where that assumption is
valid; it's merely non-portable.

If code that depended on implementation-defined characteristics
were considered to invoke undefined behavior, there'd be no
point in requiring implementations to document this undefined
behavior. Though this particular case is a bit unusual, since it's
implementation-defined whether a given program invokes undefined
behavior or not.
 
K

Keith Thompson

pete said:
It's unusual because you know better than to write code that way.

Not necessarily. I might have a perfectly valid reason to want to
create a text file with no terminating new-line, if the implementation
permits it.

For example, suppose I want to create a modified version of an
existing text file, with each occurrence of "foo" changed to "bar".
(For something that simple I wouldn't write a new program, but you get
the idea.) If the input file doesn't have a trailing new-line, I
probably wouldn't want to add one to the output file.
But it's easy to conjure up expressions
which are implementation defined
as to whether or not their evaluation causes undefined behavior.

(-INT_MIN)

(USHRT_MAX + 1)

(1 << 16)

(1 / (CHAR_BIT - 8))

Good point.
 
C

CBFalconer

Keith said:
.... snip ...


Which means that, even on systems that don't require a trailing
new-line, you can't distinguish between a text file that has a
trailing new-line and one that doesn't. Some might consider
that a disadvantage.

Right, but it's documented. If it causes problems, you can always
not use it (or modify it). If you look at code using fgets the
first thing it normally does is remove any '\n', or assume it is a
partial line.
 
D

David Thompson

Keith Thompson said:
[...]
I argue that this:
int main() { /* ... */ }
is *not* equivalent to this:
int main(void) { /* ... */ }
[...]
Probably adding the wording for "int main()" to the normative text or to
the footnote 9 (I'm using N1256) seems to be necessary to clarify the
intent.

This would allow

int main(argc, argv, envp)
int argc;
char **argv;
char **envp;
{}

because the defined type is int main().

What if "It shall be defined with [...]" were changed to "It shall be
(defined as) compatible with [...]"? This, I believe, allows old-style
definitions that actually define main with 0 or 2 parameters of the
appropriate type, without allowing other old-style definitions.

Sorry, that makes it worse. function types declared or defined
old-style are _compatible_ based only on return type regardless of
their parameters. ALL of the following:
int main () { }
int main (x, y, z) double x; FILE y; _Complex z; { }
int main (q) size_t (*q) (size_t (*) ()); { }
are compatible with EITHER of:
int main (void)
int main (int, char**)
but those two aren't compatible with each other; it's not transitive.

I think it's obvious what was meant is that main must return int and
take either no parameters (specified either oldstyle or new) or two
parameters one int and one char** (ditto). The type system differs
oldstyle vs newstyle for hysterical raisins, making this clumsy.
What we want is a notion of 'effectively same function type' that
isn't directly defined elsewhere in the Standard, although 6.5.2.2p6-9
covers most of the ground (except varargs, which don't apply here).
We probably could say something like 'main must be defined such that
it can be called as one of int(*)(void) or int(*)(int,char**)
correctly per 6.5.2.2 possibly excluding the special dispensation for
unsigned=signed int' but IMO that's _less_ helpful.

The Standard needs to care about making the initial call work, since
that's critical to every (hosted) program. The _declared_ type of main
differs for oldstyle vs newstyle, but matters only for recursive calls
which are pretty useless outside IOCCC. <OT> C++ prohibits them. </>

That said, I don't believe anyone competent to be an implementor has
ever misunderstood this rather simple and basic provision, and it
would be a mistake for the committee members who already don't have
overmuch time for actual problems to waste their time on this.
Fortunately(?) many if not all here apparently have time to waste.

Smiley omitted, after (unhappy) reconsideration. This is the sort of
thing that might actually lead me to join the grumpiness campaign, if
it still exists and hasn't been taken over by the int64 campaign. <G>
 
K

Kenny McCormack

....
Omitting a newline character when write something to a text stream
does not cause undefined behavior, even if code containing such a
construction is not strictly conforming.

Angels, pins, dancing...

(*) Prototyping main - *and* the missing newline. Heady topics, indeed.
 

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
473,997
Messages
2,570,239
Members
46,828
Latest member
LauraCastr

Latest Threads

Top