Does your C compiler support "//"? (was Re: using structures)

R

Richard Heathfield

Ross said:
But since they haven't been written and won't be written this makes
a strictly conforming program a much more theoretical concept than a
practical one.

Not at all. I haven't written millions of filter programs. But I think I can
reasonably lay claim to hundreds.
Strictly conforming programmes are class of programs
that in theory could be written but in practice aren't.

In practice, I write a lot of programs that I strive to make portable to
/any/ hosted environment, without modification. The fact that you do not
write such programs (or at least I presume, from what you say, that you do
not) does not mean that nobody else does.
 
J

James Kuyper

Douglas A. Gwyn said:
Keith Thompson wrote: ....

That not so, since it is an important component of
programming for portability, which is economically
important.

It can be used for that purpose only after extensive modification. It
would be better if the modifications were part of the original
definition.
Hopefully the *wrong* propaganda being promulgated by
opponents of the C standard is recognized as such and
is generally disregarded by real-world programmers.

I assume that I'm one of the targets of that accusation. I am anything
but an opponent of the C standard. I believe in standardization, and I
like the C standard overall. It's only because I basically approve of
the standard that I bother criticizing it. I wouldn't waste my time with
detailed criticism of a standard that wasn't basically worth-while.

I think that the definition of strictly-conforming code is being
generally disregarded by real-world programmers. I suspect that they're
using some other concept of conformance that is more useful by reason of
being more lenient. I also suspect that they're suffering from the fact
that this looser concept is poorly-defined and not officially
standardardized.
 
J

James Kuyper

:
....
to support a contrary claim. I'm telling you what was
meant, and that the contrary interpretation is silly.

Since the contrary interpretation is the only one consistent with the
actual words of the standard, then the fact that it is silly constitutes
evidence that those words need to be changed.
 
S

Stewart Brodie

James Kuyper said:
I think that the definition of strictly-conforming code is being generally
disregarded by real-world programmers. I suspect that they're using some
other concept of conformance that is more useful by reason of being more
lenient. I also suspect that they're suffering from the fact that this
looser concept is poorly-defined and not officially standardardized.

Yes, I would agree with that. Assuming you can find programmers who
actually care about avoiding implementation-defined behaviour, undefined
behaviour et al., that is.

One team I was working with on a product to run on Linux wanted to make sure
they stuck as closely as possible to s.c. code so that when somebody had the
bright idea of porting it to at least another UNIX-like platform, as much as
the code as possible would be safe. Initially, a lot of time was spent
(wasted?) trying to find s.c. solutions to various problems when a
quick'n'dirty hack would have done - although it was felt that s.c.
solutions should exist and should be used if possible.

In the end, the s.c. idea was abandonned as unworkable (particularly in the
areas of signal handlers and I/O in a multi-threaded run-time environment).
What we ended up with was quite a lot of the code being s.c., but some areas
not - and that contaminates the whole application.

So in that sense, the current definition of strict-conforming code is
disregarded by many real-world programmers because it is of no practical use
to them.

We have used objects of type 'int' in our code to hold values greater than
32767. This exceeds the minimum required maximum, therefore the code is not
s.c.

BTW, when checking that, I re-read what the standard says about the 'int'
type. 6.2.5p2 merely says it takes on the natural size for the execution
environment. The only constraint I can find is that the range of values
that can be represented in implemention-defined subject to the a minimum
representable range between -32767 and +32767, according to the limits
defined in limits.h (5.2.4.2.1). Does that make the size of 'int' objects
implicitly implementation-defined, or does it just result in unspecified
behaviour when you use an 'int'? Under either interpretation, you cannot
write a strictly-conforming program at all, since main returns 'int'. Is
there some information I have overlooked which provides scope for an
alternative interpretation?
 
R

Richard Damon

Would it be possible to consider that the errors during output as inputs to the
program? (In one sense they are as it is data that comes to the program from to
OS or hardware when the write is issued). This should have the effect of
negating the argument that any output renders the program non-SC due to the
possibility of I/O errors, as now the (non)presence of I/O errors would be
specified by the input given to the program. It would say that a given
implementation may not be able to generate an arbitrary input condition (like no
error with more output then the device can hold) but would allow us to define
what the output should be for all inputs (with error condition specifications)
which the system can generate.
 
R

Ross Ridge

Ross said:
But since they haven't been written and won't be written this makes
a strictly conforming program a much more theoretical concept than a
practical one.

Richard Heathfield said:
Not at all. I haven't written millions of filter programs. But I think I can
reasonably lay claim to hundreds.

I'm sceptical that more than handful of them are strictly conforming.
In practice, I write a lot of programs that I strive to make portable to
/any/ hosted environment, without modification.

That doesn't make them strictly conforming.
The fact that you do not write such programs (or at least I presume,
from what you say, that you do not) does not mean that nobody else does.

I write all sort of programmes. From ones that will only work on one
machine, to ones that will run any hosted enviroment that actually exists.
One job I had was maintaing a complete set of Unix utilities, including
many filters, that didn't assume ASCII, or two-complement arithmetic,
or 32-bit ints. No other set of Unix utilities are as portable, and
indeed as widely ported. But none of them were strictly conforming.

Quite frankly, I don't think you have as much experience working
on portable code as I do. I suspect in that in practice you haven't
actually ported your code to a very wide range of enviroments.

But the fact remains, as practical matter almost no strictly conforming
programmes are written.

Ross Ridge
 
R

Richard Heathfield

Ross said:
I'm sceptical that more than handful of them are strictly conforming.

Given the current wording of the Standard, I don't see how any of them can
be, since they all produce output.
That doesn't make them strictly conforming.

I agree, even modulo the above. But of course it doesn't make them /not/
strictly conforming either.
I write all sort of programmes. From ones that will only work on one
machine, to ones that will run any hosted enviroment that actually exists.
One job I had was maintaing a complete set of Unix utilities, including
many filters, that didn't assume ASCII, or two-complement arithmetic,
or 32-bit ints. No other set of Unix utilities are as portable, and
indeed as widely ported. But none of them were strictly conforming.

You are in a better position to judge that than me.
Quite frankly, I don't think you have as much experience working
on portable code as I do.

Perhaps that's true, and perhaps it isn't, but it's entirely beside the
point, which is that the wording of the Standard doesn't appear to allow
/any/ useful program (% IEFBR14, perhaps) to be strictly conforming. This
is IMHO a flaw.
 
R

Ross Ridge

James Kuyper said:
I think that the definition of strictly-conforming code is being
generally disregarded by real-world programmers. I suspect that they're
using some other concept of conformance that is more useful by reason of
being more lenient. I also suspect that they're suffering from the fact
that this looser concept is poorly-defined and not officially
standardardized.

The C standard provides two classes of program conformance, strictly
conforming programs that can run under any conforming implementation,
and conforming programs that run under a given conforming implmentation.
When C programmers want to write portable programs, and they don't
always do, then in practice they want to write a sufficiently portable
program that will run under all the implementations they're willing
to spend the effort to get it running under. This means they want it
to be portable more than just one C implmentation, but seldom do they
want it to be portable to every conforming C implementation that exists,
or could possibly ever exist.

So they have to come with a "portability standard" that comes somewhere
between strictly-conforming code and conforming code. But this standard
is going to vary from group to group, depending on what kind portabilty
they need, and so it's essentially impossible for Standard C to define
something that's going to be useful to many programmers.

All this is as I think it should be. I think a strictly conforming
programs should be defined as one that's portable to every conforming C
implementation that could ever be made. I think the C standard should
allow conforming implementations to be reasonably and effeciently
implemented on every kind of platform that C has can be reasonably and
effeciently implemented on, based historical concepts of the scope of C.
As a result, I don't think the definition of a strictly conforming
program is supposed to be something that many programmers could use as
a portiblity standard in actual practice.

To make the concept of a strictly conforming program useful in practice
to a significant number of people in the real world, you have to
greatly limit the number of systems that Standard C could reasonbly
be implemented on. And it still wouldn't useful to a lot of people,
consider that in the GNU coding standards the minimum portiblity required
is "to run on top of the GNU kernel, compiled with the GNU C compiler,
on various types of CPU."

The only thing wrong here is that the defintition of strictly conforming
is more restrictive than what is actually portable to every conforming
implementation that actually exists and we can reasonably assume to exist.
Some of that's partly because it's hard or impossible to come up a
precise enough set of requirements for various things in the standard,
including the actual definition of a strictly conforming program. But I
think there may be room for things like allowing strictly conforming
programmes to use the characters "$" and "@" in strings.

But since it's not of much practical value, I'm not bothered by the fact
that there are some problems with the definition.

Ross Ridge
 
K

Keith Thompson

Stewart Brodie said:
We have used objects of type 'int' in our code to hold values greater than
32767. This exceeds the minimum required maximum, therefore the code is not
s.c.

Code that stores values greater than 32767 in objects of type int
isn't just non-s.c., it's actually non-portable to some real world
implementations. (I'm assuming that there are still some
implementations in use that have 16-bit ints). If you don't care
about portability to such implementations, that's fine. If you do,
it's not difficult to avoid using int for large values. Using long
rather than int is the simplest approach. If you're concerned about
wasting space, use int_least32_t if it's available, or your own
equivalent if it isn't.
BTW, when checking that, I re-read what the standard says about the 'int'
type. 6.2.5p2 merely says it takes on the natural size for the execution
environment. The only constraint I can find is that the range of values
that can be represented in implemention-defined subject to the a minimum
representable range between -32767 and +32767, according to the limits
defined in limits.h (5.2.4.2.1). Does that make the size of 'int' objects
implicitly implementation-defined, or does it just result in unspecified
behaviour when you use an 'int'? Under either interpretation, you cannot
write a strictly-conforming program at all, since main returns 'int'. Is
there some information I have overlooked which provides scope for an
alternative interpretation?

The size of int is certainly implementation-defined; that doesn't mean
a program that uses int can't be s.c. For example this program:

int main(void)
{
return 0;
}

is undeniably strictly conforming under even the most stringent
interpretation. It returns an int value, but in a way that doesn't
depend on the size of type int.
 
K

Keith Thompson

Douglas A. Gwyn said:
What I said was that implementors have not been resorting
to such sophistry. Generally speaking they have understood
the compliance requirement quite well (along the lines that
I have explained). Actually I suspect that most of the
pedantic counterarguers understand what is meant quite well
also, but for reasons of their own choose to misrepresent
the requirements.

My point is that implementers can safely ignore the concept of strict
conformance. They don't have to write any strictly conforming code
themselves; a compiler or runtime library doesn't even have to be
written in C, let alone strictly conforming C. They have to create an
implementation that will accept all strictly conforming programs, but
by any reasonable or unreasonable interpretation of the definition of
"strictly conforming", they have to do that anyway to have a viable
implementation.

Consider three sample programs:

/* 1 */
int main(void)
{
return 0;
}

/* 2 */
#include <stdio.h>
int main(void)
{
printf("Hello, world\n");
return 0;
}

/* 3 */
#include <stdio.h>
int main(void)
{
const char *s = "Hello, world\n";
printf("The string literal is stored at address %p\n", (void*)s);
return 0;
}

We can all agree, I think, that the first program is strictly
conforming and the third is not, since it produces output dependent on
unspecified and/or implementation-defined behavior.

I doubt that any implementer worries about the distinction. Any
successful implementation has to handle all three of these programs in
a reasonable manner, because the failure to do so will be considered a
serious bug by users.
That not so, since it is an important component of
programming for portability, which is economically
important.

Hopefully the *wrong* propaganda being promulgated by
opponents of the C standard is recognized as such and
is generally disregarded by real-world programmers.

As far as I can tell, real-world programmers tend to ignore the entire
issue, regardless of what arguments are made about it.

And by the way, I think you're mistaken in your assumption that anyone
arguing this point is an opponent of the C standard. What I see in
this discussion is serious concern over the way the standard is
written, and an honest desire for it to say what it means.
 
D

Douglas A. Gwyn

Stewart said:
In the end, the s.c. idea was abandonned as unworkable (particularly in the
areas of signal handlers and I/O in a multi-threaded run-time environment).
What we ended up with was quite a lot of the code being s.c., but some areas
not - and that contaminates the whole application.

The rational policy is that all code should be usable in a
s.c. program *unless* there is solid justification for not
doing so. Threads being outside the scope of the C standard,
you need to augment your programming guidelines when they are
involved.
We have used objects of type 'int' in our code to hold values greater than
32767. This exceeds the minimum required maximum, therefore the code is not
s.c.

And that is inexcusably sloppy programming. If you try running
your application on a host with 16-bit words, it will fail.
It is easy to avoid this problem by use of types or typedefs
that are guaranteed to have adequate characteristics on all
(conforming) C implementations.
BTW, when checking that, I re-read what the standard says about the 'int'
type. 6.2.5p2 merely says it takes on the natural size for the execution
environment. The only constraint I can find is that the range of values
that can be represented in implemention-defined subject to the a minimum
representable range between -32767 and +32767, according to the limits
defined in limits.h (5.2.4.2.1). Does that make the size of 'int' objects
implicitly implementation-defined, or does it just result in unspecified
behaviour when you use an 'int'? Under either interpretation, you cannot
write a strictly-conforming program at all, since main returns 'int'. Is
there some information I have overlooked which provides scope for an
alternative interpretation?

Another wrong interpretation. A program can certainly make use of
unspecified behavior so long as its "output" does not depend on
which choice the implementation has made for that behavior.
 
D

Douglas A. Gwyn

Keith said:
int main(void)
{
return 0;
}
is undeniably strictly conforming under even the most stringent
interpretation.

There are actually people who have argued to the effect that
not even this program can be s.c. Of course they're wrong,
but they apparently have gained adherents.
 
D

Douglas A. Gwyn

Ross said:
The C standard provides two classes of program conformance, strictly
conforming programs that can run under any conforming implementation,
and conforming programs that run under a given conforming implmentation.

Forget about the latter. It's a category created only for
"political" reasons, and has no relevance for standards
compliance.
When C programmers want to write portable programs, and they don't
always do, then in practice they want to write a sufficiently portable
program that will run under all the implementations they're willing
to spend the effort to get it running under. This means they want it
to be portable more than just one C implmentation, but seldom do they
want it to be portable to every conforming C implementation that exists,
or could possibly ever exist.

If so, then they aren't thinking very clearly. By
programming to the standard of strict conformance,
whenever feasible, then *ensure* that that much of
their code is portable to *any* conforming C
implementation with essentially no work. (Of course
real-world compilers can have bugs necessitating
work-arounds, but that's an orthogonal issue.) There
are very few programmers wise enough to anticipate
the exact characteristics of every C implementation
to which their code might conceivably be ported;
history is full of examples of platform assumptions
that were never necessary but became embedded in code
and eventually caused major porting headaches.
consider that in the GNU coding standards the minimum portiblity required
is "to run on top of the GNU kernel, compiled with the GNU C compiler,
on various types of CPU."

And people programming to those coding standards have
created problems when their code is used in other
contexts.
 
D

Douglas A. Gwyn

Keith said:
My point is that implementers can safely ignore the concept of strict
conformance.

I don't think you will find a knowledgeable implementor who
agrees with that. Sure, in practice they need to do more
than the minimum required for standards compliance, but the
concept is central to understanding what that common minimum
requirement *is*.
As far as I can tell, real-world programmers tend to ignore the entire
issue, regardless of what arguments are made about it.

That doesn't mean that they are making the wisest decision.
And by the way, I think you're mistaken in your assumption that anyone
arguing this point is an opponent of the C standard.

I never said that. I said that there are haters of the
C standard (judging from their many remarks concerning
a variety of matters concerning the standard, not just
this one issue) who have promulgated this
misinterpretation. There may be others as well.
 
K

Keith Thompson

Douglas A. Gwyn said:
I don't think you will find a knowledgeable implementor who
agrees with that. Sure, in practice they need to do more
than the minimum required for standards compliance, but the
concept is central to understanding what that common minimum
requirement *is*.

(An aside: m-w.com says both "implementer" and "implementor" are
correct.)

Hmm. I was about to say that if the definition of "strictly
conforming", and all references to it (there aren't many), were
retroactively deleted from the standard, it wouldn't affect the
behavior of anyone working on C implementations. Then I re-read it,
and found something that implementers actually have to pay attention
to:

A conforming implementation may have extensions (including
additional library functions), provided they do not alter the
behavior of any strictly conforming program.

I'll have to think about this some more.
 
S

Stewart Brodie

Douglas A. Gwyn said:
The rational policy is that all code should be usable in a s.c. program
*unless* there is solid justification for not doing so. Threads being
outside the scope of the C standard, you need to augment your programming
guidelines when they are involved.

Indeed - and I don't believe that it should cover things like threads as
it's such a minefield, threads in particular.
And that is inexcusably sloppy programming.

No it is not, unless you are trying to write code that is strictly
conforming - that is why a great many (most?) real-world programmers ignore
the conformance criteria completely instead of trying to remain within its
bounds as far as possible.

That is a shame, because programs which are partially s.c. and the rest
conforming are useful to people, but dismissing people's code as
"inexcusably sloppy programming" doesn't tend to have a positive effect on
them - so they lose interest in conformance. IMHO.
If you try running your application on a host with 16-bit words, it will
fail. It is easy to avoid this problem by use of types or typedefs that
are guaranteed to have adequate characteristics on all (conforming) C
implementations.

The problem that we have is that of integration with the host environment -
which is outside the scope of the standard.

Realistically, our portability goals can only include portability to targets
which have an ILP32 model. The best we can do is define minimum
requirements for all of the implementation-defined features of the language
and only guarantee portability to implementations which meet our stricter
(i.e. less restrictive) limits.

The C presentation of the host ABI is defined in terms of basic C types like
'int'. Ideally, you would use typedefs like intN_t, but you can't rely on
that as those types are optional. So you end up with non-guaranteed sizes
like int_leastN_t - which, by definition, may not be N-bits and thus not
match your host ABI. The solution is probably to redefine the ABI
definition is terms of intN_t and require support for those optional types
from implementations wishing to interoperate with that ABI.
[if sizeof(int) is implementation-defined can you write any s.c. prog]
A program can certainly make use of unspecified behavior so long as its
"output" does not depend on which choice the implementation has made for
that behavior.

Yes, I'd overlooked the requirement that the output needed to depend on
implementation-defined size of int.

To clarify, the standard does not explicitly say that the size of an int is
implementation-defined. You may be able to infer the size of an int from
the implementation-defined values of INT_MIN and INT_MAX given the
requirements laid down for the representation of types, although even that
might be tricky gven the description of the "2 16-bit shorts used to
represent a 32-bit int" example given in the rationale. You should be able
to determine the number of value bits from that though. I think. Not sure.
 
L

LibraryUser

Richard said:
Ross Ridge wrote:
.... snip ...

You are in a better position to judge that than me.


Perhaps that's true, and perhaps it isn't, but it's entirely
beside the point, which is that the wording of the Standard
doesn't appear to allow /any/ useful program (% IEFBR14,
perhaps) to be strictly conforming. This is IMHO a flaw.

I think it has to be a truism that any program requires at least
a means of emitting results. If it is to emit anything other
that what is built into it, it also needs a means of receiving
data.

These features, in C, are fulfilled by the existence of stdin and
stdout. No further mumbo-jumbo about files, directories, etc.
are strictly necessary. We can even dispense with stdin for the
case where it does nothing but dump a predetermined output, where
it (the program) can be replaced by a pre-printed sheet(s) of
paper.

The normal usage of stderr complicates this, and could even be
considered as the fundamental implementation of stdout. Or it
could be considered another non-essential feature of the
(optional) file system.
 
K

Kevin Easton

In comp.lang.c James Kuyper said:
It can be used for that purpose only after extensive modification. It
would be better if the modifications were part of the original
definition.

May I suggest something along the lines of "a program that must, under
any and all particular allowed sequence of standard library function
actions, produce the same output on all conforming implementations".
The intention being that this:

#include <stdio.h>
#include <stdlib.h>

int main()
{
void *p = malloc(100);
if (p) {
puts("malloc succeeded.\n");
} else {
puts("malloc failed.\n");
}
free(p);
return 0;
}

would meet the definition. The allowed sequences of standard library
function actions are:

1. malloc allocates 100 bytes and returns a pointer that compares
unequal to NULL. puts successfully writes the string "malloc
succeeded.\n" to the standard output stream.

2. malloc allocates 100 bytes and returns a pointer that compares
unequal to NULL. puts fails to write the string.

3. malloc fails and returns NULL. puts successfully writes the
string "malloc failed.\n" to the standard output stream.

3. malloc fails and returns NULL. puts fails to write the string.

Any conforming implementation must produce the same output as any other
conforming implementation under each scenario, so the program meets the
definition.

Programs that do things like shifts of negative numbers (and print the
result) would not meet the defintion.

I'm sure it would take a lot more space to write the defintion out in an
easily-understood and correct manner, but I believe it would be
possible.

- Kevin.
 
K

Kevin Easton

In comp.lang.c Stewart Brodie said:
We have used objects of type 'int' in our code to hold values greater than
32767. This exceeds the minimum required maximum, therefore the code is not
s.c.

Why didn't you use "long"?
BTW, when checking that, I re-read what the standard says about the 'int'
type. 6.2.5p2 merely says it takes on the natural size for the execution
environment. The only constraint I can find is that the range of values
that can be represented in implemention-defined subject to the a minimum
representable range between -32767 and +32767, according to the limits
defined in limits.h (5.2.4.2.1). Does that make the size of 'int' objects
implicitly implementation-defined, or does it just result in unspecified
behaviour when you use an 'int'?

The size of int objects is implementation defined.
Under either interpretation, you cannot
write a strictly-conforming program at all, since main returns 'int'. Is
there some information I have overlooked which provides scope for an
alternative interpretation?

A strictly conforming program may include unspecified or
implementation-defined behaviour, just so long as the output doesn't
depend on it. So, this means you can use ints - as long as the output
doesn't depend on what happens when you try to store a number outside of
the range -32767 to 32767 in it. Eg:

Strictly Conforming:

#include <stdlib.h>

int main()
{
int n = 4000;

if (n > 3999)
return(EXIT_SUCCESS);

return EXIT_FAILURE;
}

Non-SC:
#include <stdlib.h>

int main()
{
int n = 40000;

if (n > 3999)
return(EXIT_SUCCESS);

return EXIT_FAILURE;
}

In fact this last program isn't even a correct C program, I don't
believe (because its behaviour isn't defined).

A more concrete example of correct-but-not-SC (at least, I think the
intended meaning) is a program that shifts a negative number and then
prints the result.

- Kevin.
 

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,147
Messages
2,570,833
Members
47,380
Latest member
AlinaBlevi

Latest Threads

Top