Discussion:
Using fread function
(too old to reply)
janus
2017-01-29 18:07:18 UTC
Permalink
Raw Message
Hello All,

I just noticed that swapping the positions of the inner parameters does not have any material effect on result. That led me to think that "fread" function just multiple the two parameters.

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

size_t fread(void *ptr, size_t nmemb, size_t size, FILE *stream);

Is my position correct?

Happy Sunday!

Janus
Stefan Ram
2017-01-29 18:13:11 UTC
Permalink
Raw Message
Post by janus
I just noticed that swapping the positions of the inner
parameters does not have any material effect on result. That
led me to think that "fread" function just multiple the two
parameters.
Check out the return value.
James R. Kuyper
2017-01-29 19:31:59 UTC
Permalink
Raw Message
Post by janus
Hello All,
I just noticed that swapping the positions of the inner parameters
does not have any material effect on result. ...
What "material effects" did you look at? You apparently missed a couple
of important effects.
Post by janus
... That led me to think
that "fread" function just multiple the two parameters.
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
Since C99, according to 7.21,.8.1p1, the correct prototype is

size_t fread(void * restrict ptr,
size_t size, size_t nmemb,
FILE * restrict stream);

The significance of this change from C90 is that it's now explicitly
undefined behavior if there's any overlap between the FILE object
pointed at by stream, and the first size*nmemb bytes of the memory
pointed at by ptr. I believe that it also means that it's undefined
behavior for that block of memory to overlap the location where errno is
stored. I can't imagine that it has ever been safe to make such a calls
to fread(), but the standard has never said so directly. In C99 the
"restrict" keyword was introduced, which provided a convenient way of
implying that problem. It still doesn't say so directly - you need to
understand the "restrict" keyword in order to figure out the implications.
Post by janus
size_t fread(void *ptr, size_t nmemb, size_t size, FILE *stream);
Is my position correct?
"The fread function returns the number of elements successfully read,
which may be less than nmemb if a read error or end-of-file is
encountered." (7.21.8.1p3)

A successful call to fread(ptr, size, nmemb, stream) will therefore
always return the value of nmemb. If it isn't successful, due to
reaching the end of the file after reading N bytes, but before reading
the nmemb elements, fread() will return N/size.

If N % size > 0, then fread() will have read a partial element. "If a
partial element is read, its value is indeterminate." (7.21.8.1p2).
Naively, you might expect that it would have filled the first N%size
bytes of that partial element, leaving the remaining bytes unchanged.
However, 7.21.8.1p2 means that this expectation need not be valid. You
should consider the entire "size" bytes of the partial element to be
unusable. Therefore, the first argument determine how large a portion of
the input data has an indeterminate value.

That's a total of three different ways that "size" has a different
effect on the results than "nmemb".
s***@casperkitty.com
2017-01-30 16:03:23 UTC
Permalink
Raw Message
Post by James R. Kuyper
The significance of this change from C90 is that it's now explicitly
undefined behavior if there's any overlap between the FILE object
pointed at by stream, and the first size*nmemb bytes of the memory
pointed at by ptr.
A "restrict" qualifier may be suggestive of that, but it wouldn't prove
anything. It would be possible to write a version of "memmove" which
included restrict qualifiers on both memory arguments but had defined
behavior in all cases where memmove would do so. Something like:

void *memmove(void * restrict dest, void const * restrict src,
size_t count)
{
unsigned char const * restrict src2=src;
unsigned char * restrict dest2=dest;
for (size_t i=0; i<count; i++)
{
if ((unsigned char*)src+i == dest2) // dest within src
{
for (size_t j=count; j--; )
dest2[j]=(dest2-i)[j];
return dest;
}
if (dest2+i == src) // src within dest
{
for (size_t j=0; j<count; j++)
dest2[j] = (dest2+i)[j];
return dest;
}
}
src2 = src;
for (size_t i=0; i<count; i++)
dest2[i] = src2[i];
return dest;
}

Note that if the source and destination overlap all accesses will be done
with a pointer derived from dest, thereby honoring the "restrict" qualifier.
All pointer arithmetic will be in bounds if src and dest identify regions
large enough for the copy to succeed, and the == operator is defined both
for pointers within the same object and for pointers to disjoint objects.
Tim Rentsch
2017-02-01 21:59:08 UTC
Permalink
Raw Message
Post by janus
Hello All,
I just noticed that swapping the positions of the inner parameters
does not have any material effect on result. ...
What "material effects" did you look at? You apparently missed a
couple of important effects.
Post by janus
... That led me to think
that "fread" function just multiple the two parameters.
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
Since C99, according to 7.21,.8.1p1, the correct prototype is
size_t fread(void * restrict ptr,
size_t size, size_t nmemb,
FILE * restrict stream);
The significance of this change from C90 is that its now explicitly
undefined behavior if there's any overlap between the FILE object
pointed at by stream, and the first size*nmemb bytes of the memory
pointed at by ptr. [...]
Is it? I agree that the intention in such cases is that they be
undefined behavior, but AFAIK there is no explicit statement in
the Standard that makes such a rule. Based just on the function
prototype, we can't conclude anything about how the function is
defined (ie, in this respect), since the two 'restrict's do not
participate in type compatibility. Is there some passage in
the Standard that makes this inference iron-clad, or is it just
a guess at what was meant? If there is such a passage, what is
it (or are they)?
j***@verizon.net
2017-02-05 19:40:51 UTC
Permalink
Raw Message
...
Post by Tim Rentsch
Post by James R. Kuyper
Since C99, according to 7.21,.8.1p1, the correct prototype is
size_t fread(void * restrict ptr,
size_t size, size_t nmemb,
FILE * restrict stream);
The significance of this change from C90 is that its now explicitly
undefined behavior if there's any overlap between the FILE object
pointed at by stream, and the first size*nmemb bytes of the memory
pointed at by ptr. [...]
Is it? I agree that the intention in such cases is that they be
undefined behavior, but AFAIK there is no explicit statement in
the Standard that makes such a rule. Based just on the function
prototype, we can't conclude anything about how the function is
defined (ie, in this respect), since the two 'restrict's do not
participate in type compatibility. Is there some passage in
the Standard that makes this inference iron-clad, or is it just
a guess at what was meant? If there is such a passage, what is
it (or are they)?
Sorry for taking so long to reply. I recognized the issue you raised as soon as I read your message, but I wanted to check every relevant detail before responding, and I didn't have time to do so before today.

Qualifiers that are applied directly to the parameters in a function prototype that is not a function definition are pretty much completely irrelevant (this is not true of qualifiers that apply to the pointed-at type of a pointer parameter, rather than to the parameter itself). Arguments to a prototyped function are converted to the unqualified version of the corresponding parameter's type (6.5.2.2p2). Qualifiers on parameters of function declarations are ignored when determining whether or not the corresponding types are compatible (6.7.6.3p15). The requirement that "All declarations that refer to the same ... function shall have compatible type; otherwise, the behavior is undefined." (6.2.7p2) does not, therefore, require that parameter types in different declarations be identically qualified.
In particular, this means that the parameter types in a function definition's declaration need not have the same qualifiers that they had in any other declaration of that same function.
The consequences of a parameter's qualifier apply only to lvalue expressions (6.7.3p4) involving the qualified identifier, which can occur only inside the definition of the function that the parameter is part of. Therefore, the "restrict" qualifiers that the standard specifies for standard library functions in section 7 would technically be completely meaningless, even if the standard did require that C standard library functions be implemented in C (which it does not).

I don't think those qualifiers are intended to be meaningless. I think that they were intended to convey permission for implementors to perform the same optimizations within the implementation of standard library routines that would be permitted if they were implemented in C using those prototypes in the function definition. I recommend that all developers assume that this is the case, and therefore avoid code that would have would have undefined behavior if it were the case. However, I concede that I cannot find any wording in the standard that says anything of the kind.

Section 6.7.3.1 of the Rationale mentions that

"The restrict qualifier can be used to express the restriction on overlap in a new prototype that is compatible with the original version:"
void *memcpy(void * restrict s1, const void * restrict s2,
size_t n);"

The Rationale is not normative, but gives insight into the committee's intent.
Tim Rentsch
2017-02-09 06:04:05 UTC
Permalink
Raw Message
...
Post by Tim Rentsch
Post by James R. Kuyper
Since C99, according to 7.21,.8.1p1, the correct prototype is
size_t fread(void * restrict ptr,
size_t size, size_t nmemb,
FILE * restrict stream);
The significance of this change from C90 is that its now explicitly
undefined behavior if there's any overlap between the FILE object
pointed at by stream, and the first size*nmemb bytes of the memory
pointed at by ptr. [...]
Is it? I agree that the intention in such cases is that they be
undefined behavior, but AFAIK there is no explicit statement in
the Standard that makes such a rule. Based just on the function
prototype, we can't conclude anything about how the function is
defined (ie, in this respect), since the two 'restrict's do not
participate in type compatibility. Is there some passage in
the Standard that makes this inference iron-clad, or is it just
a guess at what was meant? If there is such a passage, what is
it (or are they)?
Sorry for taking so long to reply. I recognized the issue you raised
as soon as I read your message, but I wanted to check every relevant
detail before responding, and I didn't have time to do so before
today.
No worries. I appreciate the double check.
Qualifiers that are applied directly to the parameters in a function
prototype that is not a function definition are pretty much
completely irrelevant (this is not true of qualifiers that apply to
the pointed-at type of a pointer parameter, rather than to the
parameter itself). Arguments to a prototyped function are converted
to the unqualified version of the corresponding parameter's type
(6.5.2.2p2). Qualifiers on parameters of function declarations are
ignored when determining whether or not the corresponding types are
compatible (6.7.6.3p15). The requirement that "All declarations that
refer to the same ... function shall have compatible type;
otherwise, the behavior is undefined." (6.2.7p2) does not,
therefore, require that parameter types in different declarations be
identically qualified.
In particular, this means that the parameter types in a function
definition's declaration need not have the same qualifiers that they
had in any other declaration of that same function.
The consequences of a parameter's qualifier apply only to lvalue
expressions (6.7.3p4) involving the qualified identifier, which can
occur only inside the definition of the function that the parameter
is part of. Therefore, the "restrict" qualifiers that the standard
specifies for standard library functions in section 7 would
technically be completely meaningless, even if the standard did
require that C standard library functions be implemented in C (which
it does not).
I don't think those qualifiers are intended to be meaningless. I
think that they were intended to convey permission for implementors
to perform the same optimizations within the implementation of
standard library routines that would be permitted if they were
implemented in C using those prototypes in the function definition.
I recommend that all developers assume that this is the case, and
therefore avoid code that would have would have undefined behavior if
it were the case. However, I concede that I cannot find any wording
in the standard that says anything of the kind.
Section 6.7.3.1 of the Rationale mentions that
"The restrict qualifier can be used to express the restriction on
overlap in a new prototype that is compatible with the original
version:"
void *memcpy(void * restrict s1, const void * restrict s2,
size_t n);"
The Rationale is not normative, but gives insight into the committee's intent.
Seems like rather a long way of saying, "I think you're right.
It seems clear that the intention is that there be undefined
behavior in such cases, but AFAICT the Standard never actually
comes right out and says so (or gives any explicit statement to
that effect)."
j***@verizon.net
2017-02-09 13:39:41 UTC
Permalink
Raw Message
On Thursday, February 9, 2017 at 1:04:12 AM UTC-5, Tim Rentsch wrote:
...
Post by Tim Rentsch
Seems like rather a long way of saying, "I think you're right.
It seems clear that the intention is that there be undefined
behavior in such cases, but AFAICT the Standard never actually
comes right out and says so (or gives any explicit statement to
that effect)."
It would have been, had that been what I wanted to say. What I wanted to say was "You're right, and here's an explanation why." Obviously, you don't need the explanation - it's for other people reading this thread. I was sufficiently aware of the relevant issues that I knew exactly what you were referring to when you made your comment. However, I was not sufficiently aware of them to avoid incorrectly expressing the message you were commenting on. That being the case, I'd expect there to be a lot of people who were not aware of the issues at all.

It's rather peculiar that, like function parameter names, qualifiers on parameters in a non-defining prototype are permitted but meaningless. I believe that they were permitted, so that the same prototype could be used for the declaration and the definition. However, because they are meaningless, it's not mandatory for the declaration and the definition to have prototypes that match in those ways. It could have been mandatory; the standard goes out of it's way to make it not mandatory, so that was clearly deliberate.
s***@casperkitty.com
2017-02-09 15:47:54 UTC
Permalink
Raw Message
Post by j***@verizon.net
It's rather peculiar that, like function parameter names, qualifiers on parameters in a non-defining prototype are permitted but meaningless. I believe that they were permitted, so that the same prototype could be used for the declaration and the definition. However, because they are meaningless, it's not mandatory for the declaration and the definition to have prototypes that match in those ways. It could have been mandatory; the standard goes out of it's way to make it not mandatory, so that was clearly deliberate.
I also find it peculiar that the Standard doesn't require that
implementations do anything useful with qualifiers like "restrict" and
"register" but requires that even implementations where they serve no
purpose must still go through the effort of validating them. In cases
where many or all implementations' natural behavior in the absence of a
qualifier would match the required behavior with the qualifier, but
either:

(1) the qualifier could allow implementations to generate more efficient
code, or

(2) the qualifier could make the code usable on platforms that were
capable of supporting the behavior at some cost but didn't do so by
default

allowing implementations that naturally support the required behavior to
"support" the qualifier by simply it would minimize the burden the qualifier
would place upon implementations.
Keith Thompson
2017-02-09 17:19:26 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by j***@verizon.net
It's rather peculiar that, like function parameter names, qualifiers
on parameters in a non-defining prototype are permitted but
meaningless. I believe that they were permitted, so that the same
prototype could be used for the declaration and the
definition. However, because they are meaningless, it's not mandatory
for the declaration and the definition to have prototypes that match
in those ways. It could have been mandatory; the standard goes out of
it's way to make it not mandatory, so that was clearly deliberate.
I also find it peculiar that the Standard doesn't require that
implementations do anything useful with qualifiers like "restrict" and
"register" but requires that even implementations where they serve no
purpose must still go through the effort of validating them. In cases
where many or all implementations' natural behavior in the absence of a
qualifier would match the required behavior with the qualifier, but
(1) the qualifier could allow implementations to generate more efficient
code, or
(2) the qualifier could make the code usable on platforms that were
capable of supporting the behavior at some cost but didn't do so by
default
allowing implementations that naturally support the required behavior to
"support" the qualifier by simply it would minimize the burden the qualifier
would place upon implementations.
I think you accidentally a word. Did you mean "by simply *ignoring*
it"? If so, what exactly do you mean by that?

Are you suggesting that an implementation that doesn't do anything
useful with "restrict" should be able to ignore it altogether, so that

int n = restrict 42;

would be quietly treated as a valid declaration? Or that an
implementation that ignores register should allow the address of a
register-qualified object to be taken?

If so, why?

If I write code that uses "register" or "restrict", I want my compiler
to check my code for validity, whether they have any semantic impact or
not.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
s***@casperkitty.com
2017-02-09 17:55:54 UTC
Permalink
Raw Message
Post by Keith Thompson
Are you suggesting that an implementation that doesn't do anything
useful with "restrict" should be able to ignore it altogether, so that
int n = restrict 42;
would be quietly treated as a valid declaration? Or that an
implementation that ignores register should allow the address of a
register-qualified object to be taken?
If so, why?
If I write code that uses "register" or "restrict", I want my compiler
to check my code for validity, whether they have any semantic impact or
not.
If an implementation isn't going to do anything useful with "restrict",
would it be more useful to have the authors spend a day or more adding
logic to deal with all the places where the keyword is or is not allowed
to appear syntactically, or would it be more useful to have the author
spend a day on some other feature which would improve the behavior of
programs that can actually run?

I would not disagree that--all else being equal--an implementation which
ensured that "restrict" was only used in spots where it is legal could
be regarded as being of higher quality than one which will accept it just
about anywhere, but if in the judgment of the implementer the time that
would be required to achieve that could be more usefully spent in some
other fashion, I would not regard the value of having compilers validate
the usage of "restrict" as being so enormous as to justify overriding the
implementer's judgment.

Incidentally, one of the reasons I favor optional features is that there
are some platforms for which compilers cannot be effectively upgraded;
certain newer language features could be supported on those platforms by
feeding code through utilities that would convert those constructs to
platforms the older platform can support, but handling other features
would be more difficult. Having the newer Standards recognize a category
of implementations which support many new features but not all of them
would seem nicer than simply saying that the Standard is no longer
applicable to older platforms.
Keith Thompson
2017-02-09 20:10:46 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Keith Thompson
Are you suggesting that an implementation that doesn't do anything
useful with "restrict" should be able to ignore it altogether, so that
int n = restrict 42;
would be quietly treated as a valid declaration? Or that an
implementation that ignores register should allow the address of a
register-qualified object to be taken?
If so, why?
If I write code that uses "register" or "restrict", I want my compiler
to check my code for validity, whether they have any semantic impact or
not.
If an implementation isn't going to do anything useful with "restrict",
would it be more useful to have the authors spend a day or more adding
logic to deal with all the places where the keyword is or is not allowed
to appear syntactically, or would it be more useful to have the author
spend a day on some other feature which would improve the behavior of
programs that can actually run?
Rhetorical questions ignored.
Post by s***@casperkitty.com
I would not disagree that--all else being equal--an implementation which
ensured that "restrict" was only used in spots where it is legal could
be regarded as being of higher quality than one which will accept it just
about anywhere, but if in the judgment of the implementer the time that
would be required to achieve that could be more usefully spent in some
other fashion, I would not regard the value of having compilers validate
the usage of "restrict" as being so enormous as to justify overriding the
implementer's judgment.
That time has already been spent. All conforming C99 and C11 compilers
recognize the "restrict" keyword and handle it correctly, diagnosing any
uses of it that are syntactically incorrect. I presume it wasn't at all
difficult. I oppose fragmenting the language in the manner you
advocate.

[snip]
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
s***@casperkitty.com
2017-02-09 21:01:14 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by s***@casperkitty.com
I would not disagree that--all else being equal--an implementation which
ensured that "restrict" was only used in spots where it is legal could
be regarded as being of higher quality than one which will accept it just
about anywhere, but if in the judgment of the implementer the time that
would be required to achieve that could be more usefully spent in some
other fashion, I would not regard the value of having compilers validate
the usage of "restrict" as being so enormous as to justify overriding the
implementer's judgment.
That time has already been spent. All conforming C99 and C11 compilers
recognize the "restrict" keyword and handle it correctly, diagnosing any
uses of it that are syntactically incorrect. I presume it wasn't at all
difficult. I oppose fragmenting the language in the manner you
advocate.
Much of the embedded-systems world use a language which combines C89 with
a number of features from later versions of C. If the Standard
describes a feature as something which quality implementations should
support when practical, programmers would entitled to assume support for
the feature except when targeting "unusual" implementations. Recognizing
the existence of implementations that can't support all such features would
not reduce the number of implementations supporting them--it would merely
allow the Standard to say something useful about implementations which can
support all of the important features but can't practically support all of
the optional ones.

Further, I would suggest that the language would be more amenable to
optimization if it had more qualifiers which existing implementations could
process in conforming fashion without having to do anything other than pre-
define some macros. Adding qualifiers in such a way that makes it hard for
code to use them while remaining compatible with existing implementations
would seem more likely to cause language fragmentation than adding qualifiers
which can be "accepted" by old and new implementations alike.
Tim Rentsch
2017-02-12 17:36:25 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by j***@verizon.net
It's rather peculiar that, like function parameter names, qualifiers
on parameters in a non-defining prototype are permitted but
meaningless. I believe that they were permitted, so that the same
prototype could be used for the declaration and the definition.
However, because they are meaningless, it's not mandatory for the
declaration and the definition to have prototypes that match in those
ways. It could have been mandatory; the standard goes out of it's
way to make it not mandatory, so that was clearly deliberate.
I also find it peculiar that the Standard doesn't require that
implementations do anything useful with qualifiers like "restrict" and
"register" but requires that even implementations where they serve no
purpose must still go through the effort of validating them. [...]
It does because the point of a language standard is to define
a standard language. Apparently that's a deeper concept than
I realized.
s***@casperkitty.com
2017-02-12 18:52:42 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by s***@casperkitty.com
I also find it peculiar that the Standard doesn't require that
implementations do anything useful with qualifiers like "restrict" and
"register" but requires that even implementations where they serve no
purpose must still go through the effort of validating them. [...]
It does because the point of a language standard is to define
a standard language. Apparently that's a deeper concept than
I realized.
What fraction of tasks that are done by programs written for various C
implementations could be accomplished by Strictly Conforming programs in
a way that was just as readable and just as efficient?

The "language" in which Strictly Conforming programs can be written may be
usable for some purposes, but it is totally unsuitable for most of the
tasks which are performed by programs written in various dialects of C.

I would regard as important the ability of a compiler to usefully produce
executable programs that perform various tasks. A quality compiler for
some platform should be compatible with existing code for architecturally-
compatible platforms, and should seek to provide diagnostics in cases where
code is unlikely to behave as intended. Supplying diagnostics in cases
where there is no reason to believe the program's behavior would not match
the programmer's intent is far less important.
Tim Rentsch
2017-02-20 05:19:43 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Tim Rentsch
Post by s***@casperkitty.com
I also find it peculiar that the Standard doesn't require that
implementations do anything useful with qualifiers like "restrict" and
"register" but requires that even implementations where they serve no
purpose must still go through the effort of validating them. [...]
It does because the point of a language standard is to define
a standard language. Apparently that's a deeper concept than
I realized.
What fraction of tasks that are done by programs written for various C
implementations could be accomplished by Strictly Conforming programs in
a way that was just as readable and just as efficient?
The "language" in which Strictly Conforming programs can be written may be
usable for some purposes, but it is totally unsuitable for most of the
tasks which are performed by programs written in various dialects of C.
You are confusing two different classes of program here, to wit,
programs that are written in standard C, and programs that are
strictly conforming. My comment is about standard C, not about
C programs that are strictly conforming.
s***@casperkitty.com
2017-02-20 17:35:42 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by s***@casperkitty.com
The "language" in which Strictly Conforming programs can be written may be
usable for some purposes, but it is totally unsuitable for most of the
tasks which are performed by programs written in various dialects of C.
You are confusing two different classes of program here, to wit,
programs that are written in standard C, and programs that are
strictly conforming. My comment is about standard C, not about
C programs that are strictly conforming.
The Standard defines two classes of programs: those which are Strictly
Conforming, and those which are Conforming but not Strictly Conforming.
I would interpret the class of "Strictly Conforming" programs as including
some which make use of some implementation-defined behaviors but will meet
their stated requirements with any combination of such behaviors that
conforming implementations could define (and thus to not rely upon any
Implementation Defined behaviors being defined in any *particular* fashion).

The Standard does not define any category of "Standard C" programs other
than the above, and the category of "Conforming" programs is so broad that
I don't think all such programs can be meaningfully described as being in
the same language, so if you're not referring to the category of "Strictly
Conforming" programs extended as above, to what are you referring?
Keith Thompson
2017-02-20 17:52:08 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Tim Rentsch
Post by s***@casperkitty.com
The "language" in which Strictly Conforming programs can be written may be
usable for some purposes, but it is totally unsuitable for most of the
tasks which are performed by programs written in various dialects of C.
You are confusing two different classes of program here, to wit,
programs that are written in standard C, and programs that are
strictly conforming. My comment is about standard C, not about
C programs that are strictly conforming.
The Standard defines two classes of programs: those which are Strictly
Conforming, and those which are Conforming but not Strictly Conforming.
I would interpret the class of "Strictly Conforming" programs as including
some which make use of some implementation-defined behaviors but will meet
their stated requirements with any combination of such behaviors that
conforming implementations could define (and thus to not rely upon any
Implementation Defined behaviors being defined in any *particular* fashion).
Isn't it simpler (and more accurate) just to use the definition in the
standard?

A strictly conforming program shall use only those features
of the language and library specified in this International
Standard. It shall not produce output dependent on any
unspecified, undefined, or implementation-defined behavior,
and shall not exceed any minimum implementation limit.

A program that's required to print the value of INT_MAX will meet its
stated requirement, but it cannot be strictly conforming because its
output depends on something that's implementation-defined. (I'm
assuming that the implementation-defined value of INT_MAX constitutes
implementation-defined behavior. If not, it shouldn't be difficult to
construct another example.)

Strict comformance is, as the name implies, a strict requirement, one
that most programs don't meet.

A "conforming program" is "one that is acceptable to a conforming
implementation". This includes programs that depend on
implementation-specific extensions, or even on undefined behavior.
Since a conforming implementation may *accept* a program containing `i =
i++`, such a program can be "conforming". It is an almost uselessly
wide category.
Post by s***@casperkitty.com
The Standard does not define any category of "Standard C" programs other
than the above, and the category of "Conforming" programs is so broad that
I don't think all such programs can be meaningfully described as being in
the same language, so if you're not referring to the category of "Strictly
Conforming" programs extended as above, to what are you referring?
There's also this (4p3):

A program that is correct in all other aspects, operating on correct
data, containing unspecified behavior shall be a correct program and
act in accordance with 5.1.2.3.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
s***@casperkitty.com
2017-02-20 19:15:52 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by s***@casperkitty.com
The Standard defines two classes of programs: those which are Strictly
Conforming, and those which are Conforming but not Strictly Conforming.
I would interpret the class of "Strictly Conforming" programs as including
some which make use of some implementation-defined behaviors but will meet
their stated requirements with any combination of such behaviors that
conforming implementations could define (and thus to not rely upon any
Implementation Defined behaviors being defined in any *particular* fashion).
Isn't it simpler (and more accurate) just to use the definition in the
standard?
A strictly conforming program shall use only those features
of the language and library specified in this International
Standard. It shall not produce output dependent on any
unspecified, undefined, or implementation-defined behavior,
and shall not exceed any minimum implementation limit.
A program that's required to print the value of INT_MAX will meet its
stated requirement, but it cannot be strictly conforming because its
output depends on something that's implementation-defined. (I'm
assuming that the implementation-defined value of INT_MAX constitutes
implementation-defined behavior. If not, it shouldn't be difficult to
construct another example.)
I was trying to suggest a guess at what you might be meaning by your use
of the term "Standard C Program". I think it unlikely that the authors of
the Standard would have expected that recognizing the category of programs
which match their definition of "Strictly Conforming Program" would be more
useful than recognizing the category of programs I described, especially
given that things like the output character set, the relationship between
the first argument given to fopen() and physical disk files, etc. are all
Implementation Defined.

I would say that if a program's stated purpose is to output any odd number
in decimal format, then a program which outputs UINT_MAX in decimal format
would satisfy that requirement regardless of the value of UINT_MAX. If
one wanted to define a category of programs which were allowed to make use
of Implementation Defined behaviors internally but were required to always
produce the same output regardless of how such behaviors were defined, that
would require adding additional language to define what "the same output"
would mean as applied to systems which handle I/O differently.
Post by Keith Thompson
Strict comformance is, as the name implies, a strict requirement, one
that most programs don't meet.
A "conforming program" is "one that is acceptable to a conforming
implementation". This includes programs that depend on
implementation-specific extensions, or even on undefined behavior.
Since a conforming implementation may *accept* a program containing `i =
i++`, such a program can be "conforming". It is an almost uselessly
wide category.
Indeed so.
Post by Keith Thompson
Post by s***@casperkitty.com
The Standard does not define any category of "Standard C" programs other
than the above, and the category of "Conforming" programs is so broad that
I don't think all such programs can be meaningfully described as being in
the same language, so if you're not referring to the category of "Strictly
Conforming" programs extended as above, to what are you referring?
A program that is correct in all other aspects, operating on correct
data, containing unspecified behavior shall be a correct program and
act in accordance with 5.1.2.3.
What that means is that use of Unspecified Behavior does not in and of
itself cause a program to fall short of any level of conformance that it
would otherwise achieve unless one of the allowable possibilities for the
behavior in question would cause the program to fail. I don't see that
as defining any level of conformance.

So again, I ask, what do you mean by a "Standard C program"? Or, to put it
another way, what must a collection of source text do, and refrain from doing,
to qualify as a "Standard C program"?
Keith Thompson
2017-02-20 19:45:21 UTC
Permalink
Raw Message
***@casperkitty.com writes:
[...]
Post by s***@casperkitty.com
So again, I ask, what do you mean by a "Standard C program"? Or, to
put it another way, what must a collection of source text do, and
refrain from doing, to qualify as a "Standard C program"?
As far as I can tell, the first use of the phrase "Standard C program"
is in the article to which I'm replying. I suggest you figure out who
who, if anyone, actually used that phrase and ask them.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
James R. Kuyper
2017-02-20 20:38:27 UTC
Permalink
Raw Message
Post by Keith Thompson
[...]
Post by s***@casperkitty.com
So again, I ask, what do you mean by a "Standard C program"? Or, to
put it another way, what must a collection of source text do, and
refrain from doing, to qualify as a "Standard C program"?
As far as I can tell, the first use of the phrase "Standard C program"
is in the article to which I'm replying. I suggest you figure out who
who, if anyone, actually used that phrase and ask them.
He was certainly incorrect to talk about 'your use of the term "Standard
C Program"' in his response to a message of yours, since you never used
anything like that term.
However, Tim Rentsch did talk about "programs written in Standard C",
something that could reasonably be referred to as "Standard C programs".

Since Tim clearly distinguished that category from "strictly conforming
programs", it's a legitimate question to ask how he defines the term.

The only other conformance category defined by the standard for programs
is "conforming program". Most things that qualify as a "conforming
program" according to the C standard could not be sanely referred to as
"programs written in Standard C". The only feature a program can contain
that could disqualify it as a conforming program is a #error directive
that survives conditional compilation. I guarantee you that the "Code of
Hammurabi" (in the original Akkadian) contains not a single #error
directive, and therefore qualifies as a conforming C program.

"correct code" is a term used by the standard to explain the fact that a
program with unspecified behavior should not be considered incorrect
just because of that fact, and is therefore still constrained by the
requirements of 5.1.2.3 (which indirectly implies virtually every other
requirement imposed by the standard).
However, "correct program" doesn't qualify as a conformance category,
because it must be "correct in all other aspects, operating on correct
data". "correct in all other aspects" includes correctly meeting the
program's requirements, which are program-specific. The same is true of
"correct data". So "correct code" is about a lot more than just
conformance to the C standard.

If I had to hazard a guess, it would be that Tim's talking about
programs which don't have undefined behavior, but Tim should be
answering that question, not me.
Tim Rentsch
2017-02-23 20:12:17 UTC
Permalink
Raw Message
Post by James R. Kuyper
Post by Keith Thompson
[...]
Post by s***@casperkitty.com
So again, I ask, what do you mean by a "Standard C program"? Or, to
put it another way, what must a collection of source text do, and
refrain from doing, to qualify as a "Standard C program"?
As far as I can tell, the first use of the phrase "Standard C program"
is in the article to which I'm replying. I suggest you figure out who
who, if anyone, actually used that phrase and ask them.
He was certainly incorrect to talk about 'your use of the term
"Standard C Program"' in his response to a message of yours, since you
never used anything like that term.
However, Tim Rentsch did talk about "programs written in Standard C",
[...]
If you are going to quote me (ie, with text in quotation marks),
please quote me exactly.
j***@verizon.net
2017-02-24 18:37:23 UTC
Permalink
Raw Message
...
Post by Tim Rentsch
Post by James R. Kuyper
However, Tim Rentsch did talk about "programs written in Standard C",
[...]
If you are going to quote me (ie, with text in quotation marks),
please quote me exactly.
Sorry: "programs that are written in standard C".
Tim Rentsch
2017-02-23 13:04:28 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by s***@casperkitty.com
The "language" in which Strictly Conforming programs can be written may be
usable for some purposes, but it is totally unsuitable for most of the
tasks which are performed by programs written in various dialects of C.
You are confusing two different classes of program here, to wit,
programs that are written in standard C, and programs that are
strictly conforming. My comment is about standard C, not about
C programs that are strictly conforming.
The Standard defines two classes of programs: those which are Strictly
Conforming, and those which are Conforming but not Strictly Conforming.
I would interpret the class of "Strictly Conforming" programs as including
some which make use of some implementation-defined behaviors but will meet
their stated requirements with any combination of such behaviors that
conforming implementations could define (and thus to not rely upon any
Implementation Defined behaviors being defined in any *particular* fashion).
The Standard does not define any category of "Standard C" programs other
than the above, and the category of "Conforming" programs is so broad that
I don't think all such programs can be meaningfully described as being in
the same language, so if you're not referring to the category of "Strictly
Conforming" programs extended as above, to what are you referring?
Did you ever work in a job where you got paid by the word? Just
curious.

An important part of good writing is removing unnecessary stuff.
Here you could have said just "What do you mean by standard C?"

By standard C I mean the language described in the ISO C standard,
not including any constructions that would draw a mandatory
diagnostic or run afoul of compile-time undefined behavior (eg,
a line starting with # other than one of the usual pre-processing
directives). Extensions are probably okay provided they don't
alter either of the two conditions in the last sentence.
s***@casperkitty.com
2017-02-23 15:58:17 UTC
Permalink
Raw Message
Post by Tim Rentsch
By standard C I mean the language described in the ISO C standard,
not including any constructions that would draw a mandatory
diagnostic or run afoul of compile-time undefined behavior (eg,
a line starting with # other than one of the usual pre-processing
directives). Extensions are probably okay provided they don't
alter either of the two conditions in the last sentence.
That does not seem like a particularly useful category to define. It
also seems a bit ambiguous. Is the following, for example, written in
what you would call "Standard C"?

#include <stdint.h>
#include <stdio.h>
int main(void) {
int_least18_t q = 131071;
return printf("%ld\n", (long)(q+1));
}

Some implementations would reject such code together, some might be required
to output 131072, and some might accept it but yield arbitrary behavior. So
is it "standard C"?
Tim Rentsch
2017-02-25 19:48:05 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Tim Rentsch
By standard C I mean the language described in the ISO C standard,
not including any constructions that would draw a mandatory
diagnostic or run afoul of compile-time undefined behavior (eg,
a line starting with # other than one of the usual pre-processing
directives). Extensions are probably okay provided they don't
alter either of the two conditions in the last sentence.
That does not seem like a particularly useful category to define.
Hey don't blame me for your question! I was just using the
term - it was you who asked for a definition.
Post by s***@casperkitty.com
It
also seems a bit ambiguous. Is the following, for example, written in
what you would call "Standard C"?
The answer to that is a definite no. But then I didn't use
the term "Standard C".
Post by s***@casperkitty.com
#include <stdint.h>
#include <stdio.h>
int main(void) {
int_least18_t q = 131071;
return printf("%ld\n", (long)(q+1));
}
Some implementations would reject such code together, some might be required
to output 131072, and some might accept it but yield arbitrary behavior. So
is it "standard C"?
Can it be accepted by a conforming implementation, without any
mandatory diagnostics, without any compile-time undefined
behavior, and without using any extensions that would change
either of the previous two aspects? Is that a question you are
able to answer? If it is, then can you explain why you would
have trouble answering your own question?
j***@verizon.net
2017-02-25 21:44:22 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by s***@casperkitty.com
Post by Tim Rentsch
By standard C I mean the language described in the ISO C standard,
not including any constructions that would draw a mandatory
diagnostic or run afoul of compile-time undefined behavior (eg,
a line starting with # other than one of the usual pre-processing
directives). Extensions are probably okay provided they don't
alter either of the two conditions in the last sentence.
That does not seem like a particularly useful category to define.
Hey don't blame me for your question! I was just using the
term - it was you who asked for a definition.
You're the one who's use of the term prompted the question. It seems to me to
be a reasonable thing to ask you what you meant by that term.
Post by Tim Rentsch
Post by s***@casperkitty.com
It
also seems a bit ambiguous. Is the following, for example, written in
what you would call "Standard C"?
The answer to that is a definite no. But then I didn't use
the term "Standard C".
His question traces back to your message
<https://groups.google.com/d/msg/comp.lang.c/_p8LSNnsRdA/i2rVPAe5AQAJ> in which
you did introduce the term "standard C" into the discussion. It was not used in
the message you were responding to, nor in any message preceding that one. Why
are you so reluctant to accept responsibility for the meaning of a term you
introduced into the discussion? It's certainly not a term that the standard
itself defines.
Post by Tim Rentsch
Post by s***@casperkitty.com
#include <stdint.h>
#include <stdio.h>
int main(void) {
int_least18_t q = 131071;
return printf("%ld\n", (long)(q+1));
}
Some implementations would reject such code together, some might be required
to output 131072, and some might accept it but yield arbitrary behavior. So
is it "standard C"?
Can it be accepted by a conforming implementation, without any
mandatory diagnostics, without any compile-time undefined
behavior, and without using any extensions that would change
either of the previous two aspects? ...
It doesn't contain a #error directive, so a conforming implementation is
allowed to accept it. A conforming implementation is allowed to define
int_least18_t in <stdint.h>. If so, no diagnostic is required. A conforming
implementation is allowed to have INT_MAX>131071, so q+1 doesn't overflow. I
see no other possible reason why a diagnostic should be mandatory, or the
behavior should be undefined, but I might easily have missed something. Whether
int_least18_t is supported is unspecified behavior, and the value of INT_MAX is
implementation-defined - neither constitutes an extension to C. The answer to
your question seems to me to be "Yes".

Above you said "No" when asked whether this code is written in Standard C -
which feature of your definition does it violate?
Tim Rentsch
2017-04-17 20:12:07 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by s***@casperkitty.com
Post by Tim Rentsch
By standard C I mean the language described in the ISO C standard,
not including any constructions that would draw a mandatory
diagnostic or run afoul of compile-time undefined behavior (eg,
a line starting with # other than one of the usual pre-processing
directives). Extensions are probably okay provided they don't
alter either of the two conditions in the last sentence.
That does not seem like a particularly useful category to define.
Hey don't blame me for your question! I was just using the
term - it was you who asked for a definition.
You're the one who's use of the term prompted the question. It
seems to me to be a reasonable thing to ask you what you meant by
that term.
I don't mind being asked to explain what I meant. What I object
to is the insinuation that I was trying to coin a new term, or
to sharply define it - neither of which I was doing - rather than
just using a phrase in ordinary English, without needing a sharp
definition.

Note that supercat followed his usual dickish habit of oversnipping
quoted material, to obscure the context and change the subject.
Post by Tim Rentsch
Post by s***@casperkitty.com
It
also seems a bit ambiguous. Is the following, for example, written in
what you would call "Standard C"?
The answer to that is a definite no. But then I didn't use
the term "Standard C".
His question traces back to your message
<https://groups.google.com/d/msg/comp.lang.c/_p8LSNnsRdA/i2rVPAe5AQAJ> in which
you did introduce the term "standard C" into the discussion.
Yes, I used the phrase "standard C". Not "Standard C". Capitalizing
a phrase makes it a proper noun, which is exactly what I did /not/
want to do.
It was not used in the message you were responding to, nor in any
message preceding that one. Why are you so reluctant to accept
responsibility for the meaning of a term you introduced into the
discussion?
Because I didn't introduce a term, I simply wrote a phrase in
ordinary English.
s***@casperkitty.com
2017-04-17 20:50:21 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by Tim Rentsch
Post by s***@casperkitty.com
Post by Tim Rentsch
By standard C I mean the language described in the ISO C standard,
not including any constructions that would draw a mandatory
diagnostic or run afoul of compile-time undefined behavior (eg,
a line starting with # other than one of the usual pre-processing
directives). Extensions are probably okay provided they don't
alter either of the two conditions in the last sentence.
That does not seem like a particularly useful category to define.
Hey don't blame me for your question! I was just using the
term - it was you who asked for a definition.
You're the one who's use of the term prompted the question. It
seems to me to be a reasonable thing to ask you what you meant by
that term.
I don't mind being asked to explain what I meant. What I object
to is the insinuation that I was trying to coin a new term, or
to sharply define it - neither of which I was doing - rather than
just using a phrase in ordinary English, without needing a sharp
definition.
Note that supercat followed his usual dickish habit of oversnipping
quoted material, to obscure the context and change the subject.
I'm quoting all of the above, so as to avoid any accusation of selective
editing. I'll also include all of your text from Feb. 19 which I think
was where this sub-issue started:

|> On Sunday, February 12, 2017 at 11:36:31 AM UTC-6, Tim Rentsch wrote:
|>> supercat writes:
|>>> I also find it peculiar that the Standard doesn't require that
|>>> implementations do anything useful with qualifiers like "restrict" and
|>>> "register" but requires that even implementations where they serve no
|>>> purpose must still go through the effort of validating them. [...]
|>>
|>> It does because the point of a language standard is to define
|>> a standard language. Apparently that's a deeper concept than
|>> I realized.
|>
|> What fraction of tasks that are done by programs written for various C
|> implementations could be accomplished by Strictly Conforming programs in
|> a way that was just as readable and just as efficient?
|>
|> The "language" in which Strictly Conforming programs can be written may be
|> usable for some purposes, but it is totally unsuitable for most of the
|> tasks which are performed by programs written in various dialects of C.
|
|You are confusing two different classes of program here, to wit,
|programs that are written in standard C, and programs that are
|strictly conforming. My comment is about standard C, not about
|C programs that are strictly conforming.

My question was, and remains, what criteria would distinguish "programs
that are written in standard C" [your exact phrasing] from other text files
that would cause some implementations to behave in useful fashion?

You seem to offer a definition on Feb 25:

|Can it be accepted by a conforming implementation, without any
|mandatory diagnostics, without any compile-time undefined
|behavior, and without using any extensions that would change
|either of the previous two aspects? Is that a question you are
|able to answer? If it is, then can you explain why you would
|have trouble answering your own question?

but I'm not clear what exactly you mean by the last point. If some
implementations would be required to define certain types, and others
would be forbidden from doing so, should such types be regarded as
"extensions" for purposes of the above definition?

Tim Rentsch
2017-02-12 17:31:14 UTC
Permalink
Raw Message
...
Post by Tim Rentsch
Seems like rather a long way of saying, "I think you're right.
It seems clear that the intention is that there be undefined
behavior in such cases, but AFAICT the Standard never actually
comes right out and says so (or gives any explicit statement to
that effect)."
It would have been, had that been what I wanted to say. What I
wanted to say was "You're right, and here's an explanation why."
Obviously, you don't need the explanation - its for other people
reading this thread. [...]
I see. Thank you for the explanation (ie, the meta-explanation).
Keith Thompson
2017-01-29 21:14:46 UTC
Permalink
Raw Message
Post by janus
I just noticed that swapping the positions of the inner parameters
does not have any material effect on result. That led me to think that
"fread" function just multiple the two parameters.
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fread(void *ptr, size_t nmemb, size_t size, FILE *stream);
Is my position correct?
I wrote about this here:

http://stackoverflow.com/a/8589688/827263

Quick summary: fread() returns the number of elements it was able
to read, and the ordering of the 2nd and 3rd arguments lets you
define what an element is. Read a single data element if a partial
read is no better than not reading anything at all. Read in smaller
chunks if partial reads are useful.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Malcolm McLean
2017-01-30 16:18:32 UTC
Permalink
Raw Message
Post by janus
Hello All,
I just noticed that swapping the positions of the inner parameters does not have any material effect on result. That led me to think that "fread" function just multiple the two parameters.
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fread(void *ptr, size_t nmemb, size_t size, FILE *stream);
Is my position correct?
Essentially yes. Having two parameters is pretty useless and you might as well pass
in a size of memory buffer you wish to fill. It also tends to encourage code such
as

fread(x, sizeof(double), 10, fp);

which isn't very portable.

The only slight advantage is that it tells you how many doubles were read correctly.
The number of times the information "7 out of 10" is more useful than "not all ten"
is vanishingly low, however.
s***@casperkitty.com
2017-01-30 16:44:10 UTC
Permalink
Raw Message
Post by Malcolm McLean
Essentially yes. Having two parameters is pretty useless and you might as well pass
in a size of memory buffer you wish to fill. It also tends to encourage code such
as
fread(x, sizeof(double), 10, fp);
which isn't very portable.
The only slight advantage is that it tells you how many doubles were read correctly.
The number of times the information "7 out of 10" is more useful than "not all ten"
is vanishingly low, however.
I wonder if the intention was that an input stream which currently had
74 bytes but might receive more would input nine complete 8-byte values
and leave two pending? Not all operating systems could support such a
construct (they may have no way of finding out how much data is left
without trying to read it, and no way to push back data that had been
read) but for a system which could support it such a construct could be
useful.
Keith Thompson
2017-01-30 19:58:45 UTC
Permalink
Raw Message
Post by Malcolm McLean
Post by janus
I just noticed that swapping the positions of the inner parameters
does not have any material effect on result. That led me to think
that "fread" function just multiple the two parameters.
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fread(void *ptr, size_t nmemb, size_t size, FILE *stream);
Is my position correct?
Essentially yes.
Essentially no.
Post by Malcolm McLean
Having two parameters is pretty useless and you might as well pass
in a size of memory buffer you wish to fill. It also tends to encourage code such
as
fread(x, sizeof(double), 10, fp);
which isn't very portable.
How is that not portable (assuming x points to a chunk of memory big
enough to hold 10 doubles)?
Post by Malcolm McLean
The only slight advantage is that it tells you how many doubles were read correctly.
The number of times the information "7 out of 10" is more useful than "not all ten"
is vanishingly low, however.
If the distinction isn't useful, you can read a single chunk of 10
doubles. If it is, you can read 10 elements of sizeof(double) bytes
each. I presume that flexibility is quite intentional.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Malcolm McLean
2017-01-30 21:05:37 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Malcolm McLean
fread(x, sizeof(double), 10, fp);
which isn't very portable.
How is that not portable (assuming x points to a chunk of memory big
enough to hold 10 doubles)?
Because it breaks if your machine representation isn't the same as the
binary file.

I've collected a series of routines here. Even the integral cases aren't entirely straighforwards and intuitive.

https://github.com/MalcolmMcLean/ieee754
s***@casperkitty.com
2017-01-30 21:39:51 UTC
Permalink
Raw Message
Post by Malcolm McLean
Post by Keith Thompson
How is that not portable (assuming x points to a chunk of memory big
enough to hold 10 doubles)?
Because it breaks if your machine representation isn't the same as the
binary file.
For files that will be read back on the same machine as they were written,
that is a complete non-problem. Otherwise, the extremely vast majority of
C implementations use one of two representations, so a requirement that
code use a particular format would limit the simply-written code to the
implementations which use that format--not universal portability, but still
portable to a rather wide range of platforms.

If the maintainers of the C Standard want to facilitate more portable code,
they should include optional types whose exact layout would be rigidly
specified by the Standard and/or controlled by the programmer. A quality
implementation for a given platform should include, at minimum, the types
the hardware natively provides, but could also support others.

If instead of using "double" code used "__fp_ieee754_double_8l" which was
defined by the Standard as indicating an IEEE-754 double stored as eight
octets LSB first, some compilers for a big-endian machine might refuse to
accept that type, but some could generate code which performed the necessary
byte-swapping operations to use it.

Note that inclusion of such types would not "discriminate" against unusual
architectures, but quite the opposite: it would encourage people targeting
more commonplace architectures to write code in a fashion that would allow
implementations for unusual architectures to automatically generate the
bit-level code necessary to import and export data from other machines.
Keith Thompson
2017-01-30 21:57:36 UTC
Permalink
Raw Message
Post by Malcolm McLean
Post by Keith Thompson
Post by Malcolm McLean
fread(x, sizeof(double), 10, fp);
which isn't very portable.
How is that not portable (assuming x points to a chunk of memory big
enough to hold 10 doubles)?
Because it breaks if your machine representation isn't the same as the
binary file.
You're right, of course. I should have thought of that (I've made the
same point myself enough times).

[...]
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Loading...