Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #102713 > unrolled thread
| Started by | janus <emekamicro@gmail.com> |
|---|---|
| First post | 2017-01-29 10:07 -0800 |
| Last post | 2017-01-30 13:57 -0800 |
| Articles | 20 on this page of 36 — 7 participants |
Back to article view | Back to comp.lang.c
Using fread function janus <emekamicro@gmail.com> - 2017-01-29 10:07 -0800
Re: Using fread function "James R. Kuyper" <jameskuyper@verizon.net> - 2017-01-29 14:31 -0500
Re: Using fread function supercat@casperkitty.com - 2017-01-30 08:03 -0800
Re: Using fread function Tim Rentsch <txr@alumni.caltech.edu> - 2017-02-01 13:59 -0800
Re: Using fread function jameskuyper@verizon.net - 2017-02-05 11:40 -0800
Re: Using fread function Tim Rentsch <txr@alumni.caltech.edu> - 2017-02-08 22:04 -0800
Re: Using fread function jameskuyper@verizon.net - 2017-02-09 05:39 -0800
Re: Using fread function supercat@casperkitty.com - 2017-02-09 07:47 -0800
Re: Using fread function Keith Thompson <kst-u@mib.org> - 2017-02-09 09:19 -0800
Re: Using fread function supercat@casperkitty.com - 2017-02-09 09:55 -0800
Re: Using fread function Keith Thompson <kst-u@mib.org> - 2017-02-09 12:10 -0800
Re: Using fread function supercat@casperkitty.com - 2017-02-09 13:01 -0800
Re: Using fread function Tim Rentsch <txr@alumni.caltech.edu> - 2017-02-12 09:36 -0800
Re: Using fread function supercat@casperkitty.com - 2017-02-12 10:52 -0800
Re: Using fread function Tim Rentsch <txr@alumni.caltech.edu> - 2017-02-19 21:19 -0800
Re: Using fread function supercat@casperkitty.com - 2017-02-20 09:35 -0800
Re: Using fread function Keith Thompson <kst-u@mib.org> - 2017-02-20 09:52 -0800
Re: Using fread function supercat@casperkitty.com - 2017-02-20 11:15 -0800
Re: Using fread function Keith Thompson <kst-u@mib.org> - 2017-02-20 11:45 -0800
Re: Using fread function "James R. Kuyper" <jameskuyper@verizon.net> - 2017-02-20 15:38 -0500
Re: Using fread function Tim Rentsch <txr@alumni.caltech.edu> - 2017-02-23 12:12 -0800
Re: Using fread function jameskuyper@verizon.net - 2017-02-24 10:37 -0800
Re: Using fread function Tim Rentsch <txr@alumni.caltech.edu> - 2017-02-23 05:04 -0800
Re: Using fread function supercat@casperkitty.com - 2017-02-23 07:58 -0800
Re: Using fread function Tim Rentsch <txr@alumni.caltech.edu> - 2017-02-25 11:48 -0800
Re: Using fread function jameskuyper@verizon.net - 2017-02-25 13:44 -0800
Re: Using fread function Tim Rentsch <txr@alumni.caltech.edu> - 2017-04-17 13:12 -0700
Re: Using fread function supercat@casperkitty.com - 2017-04-17 13:50 -0700
Re: Using fread function Tim Rentsch <txr@alumni.caltech.edu> - 2017-02-12 09:31 -0800
Re: Using fread function Keith Thompson <kst-u@mib.org> - 2017-01-29 13:14 -0800
Re: Using fread function Malcolm McLean <malcolm.mclean5@btinternet.com> - 2017-01-30 08:18 -0800
Re: Using fread function supercat@casperkitty.com - 2017-01-30 08:44 -0800
Re: Using fread function Keith Thompson <kst-u@mib.org> - 2017-01-30 11:58 -0800
Re: Using fread function Malcolm McLean <malcolm.mclean5@btinternet.com> - 2017-01-30 13:05 -0800
Re: Using fread function supercat@casperkitty.com - 2017-01-30 13:39 -0800
Re: Using fread function Keith Thompson <kst-u@mib.org> - 2017-01-30 13:57 -0800
Page 1 of 2 [1] 2 Next page →
| From | janus <emekamicro@gmail.com> |
|---|---|
| Date | 2017-01-29 10:07 -0800 |
| Subject | Using fread function |
| Message-ID | <02c75a0c-84d7-4669-8bde-472730c7f8d3@googlegroups.com> |
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
[toc] | [next] | [standalone]
| From | "James R. Kuyper" <jameskuyper@verizon.net> |
|---|---|
| Date | 2017-01-29 14:31 -0500 |
| Message-ID | <79af9f0c-d7e1-ef68-d186-f1ce0baa9e6c@verizon.net> |
| In reply to | #102713 |
On 01/29/2017 01:07 PM, janus wrote:
> 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.
> ... 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.
> 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".
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-01-30 08:03 -0800 |
| Message-ID | <44309152-d98d-490b-aa0e-3cad8294c198@googlegroups.com> |
| In reply to | #102723 |
On Sunday, January 29, 2017 at 1:32:06 PM UTC-6, James R. Kuyper wrote:
> 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.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2017-02-01 13:59 -0800 |
| Message-ID | <kfnefzhd13n.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #102723 |
"James R. Kuyper" <jameskuyper@verizon.net> writes: > On 01/29/2017 01:07 PM, janus wrote: >> 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. > >> ... 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)?
[toc] | [prev] | [next] | [standalone]
| From | jameskuyper@verizon.net |
|---|---|
| Date | 2017-02-05 11:40 -0800 |
| Message-ID | <05a6afe0-d7db-4877-a244-1c5c7bc8e928@googlegroups.com> |
| In reply to | #102934 |
On Wednesday, February 1, 2017 at 4:59:24 PM UTC-5, Tim Rentsch wrote:
> "James R. Kuyper" <jameskuyper@verizon.net> writes:
...
> > 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.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2017-02-08 22:04 -0800 |
| Message-ID | <kfn37fn7ve2.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #103234 |
jameskuyper@verizon.net writes: > On Wednesday, February 1, 2017 at 4:59:24 PM UTC-5, Tim Rentsch wrote: >> "James R. Kuyper" <jameskuyper@verizon.net> writes: > > ... > >>> 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)."
[toc] | [prev] | [next] | [standalone]
| From | jameskuyper@verizon.net |
|---|---|
| Date | 2017-02-09 05:39 -0800 |
| Message-ID | <28dc26c8-8063-4334-9850-b1a5ba7876f3@googlegroups.com> |
| In reply to | #103512 |
On Thursday, February 9, 2017 at 1:04:12 AM UTC-5, Tim Rentsch wrote: ... > 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.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-02-09 07:47 -0800 |
| Message-ID | <d0e4b764-cef7-41d1-af6c-9b71a2ae323c@googlegroups.com> |
| In reply to | #103518 |
On Thursday, February 9, 2017 at 7:40:00 AM UTC-6, james...@verizon.net wrote:
> 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.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-02-09 09:19 -0800 |
| Message-ID | <lnwpczxowx.fsf@kst-u.example.com> |
| In reply to | #103520 |
supercat@casperkitty.com writes:
> On Thursday, February 9, 2017 at 7:40:00 AM UTC-6, james...@verizon.net wrote:
>> 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.
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-u@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"
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-02-09 09:55 -0800 |
| Message-ID | <ac73adab-30f6-42f6-b243-01b361645a03@googlegroups.com> |
| In reply to | #103538 |
On Thursday, February 9, 2017 at 11:19:16 AM UTC-6, Keith Thompson wrote: > 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.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-02-09 12:10 -0800 |
| Message-ID | <lnk28zxgzd.fsf@kst-u.example.com> |
| In reply to | #103542 |
supercat@casperkitty.com writes:
> On Thursday, February 9, 2017 at 11:19:16 AM UTC-6, Keith Thompson wrote:
>> 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.
> 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-u@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"
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-02-09 13:01 -0800 |
| Message-ID | <995cd03f-384c-4c1e-b704-6bc5114005ea@googlegroups.com> |
| In reply to | #103562 |
On Thursday, February 9, 2017 at 2:09:37 PM UTC-6, Keith Thompson wrote: > > 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.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2017-02-12 09:36 -0800 |
| Message-ID | <kfno9y72twm.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #103520 |
supercat@casperkitty.com writes: > On Thursday, February 9, 2017 at 7:40:00 AM UTC-6, james...@verizon.net wrote: >> 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.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-02-12 10:52 -0800 |
| Message-ID | <e26967e5-4cbd-4261-aea0-381fd36a0496@googlegroups.com> |
| In reply to | #103740 |
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. 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.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2017-02-19 21:19 -0800 |
| Message-ID | <kfn4lzpwia8.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #103749 |
supercat@casperkitty.com writes: > 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.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-02-20 09:35 -0800 |
| Message-ID | <ca025bfd-538e-462a-8709-aaa9aa0c5479@googlegroups.com> |
| In reply to | #104254 |
On Sunday, February 19, 2017 at 11:19:50 PM UTC-6, Tim Rentsch wrote: > supercat writes: > > 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?
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-02-20 09:52 -0800 |
| Message-ID | <lnd1ecn41j.fsf@kst-u.example.com> |
| In reply to | #104276 |
supercat@casperkitty.com writes:
> On Sunday, February 19, 2017 at 11:19:50 PM UTC-6, Tim Rentsch wrote:
>> supercat writes:
>> > 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.
> 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-u@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"
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-02-20 11:15 -0800 |
| Message-ID | <771b708b-a48b-4fde-87c1-79bbd7e2676c@googlegroups.com> |
| In reply to | #104280 |
On Monday, February 20, 2017 at 11:51:47 AM UTC-6, Keith Thompson wrote: > supercat writes: > > 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. > 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. > > 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. 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"?
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-02-20 11:45 -0800 |
| Message-ID | <ln8tp0mysu.fsf@kst-u.example.com> |
| In reply to | #104284 |
supercat@casperkitty.com writes:
[...]
> 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-u@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"
[toc] | [prev] | [next] | [standalone]
| From | "James R. Kuyper" <jameskuyper@verizon.net> |
|---|---|
| Date | 2017-02-20 15:38 -0500 |
| Message-ID | <e6d3f0eb-b12b-3029-32b6-43cece886d41@verizon.net> |
| In reply to | #104286 |
On 02/20/2017 02:45 PM, Keith Thompson wrote: > supercat@casperkitty.com writes: > [...] >> 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.
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.c
csiph-web