<http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1336.pdf>
--
Larry Jones
Another casualty of applied metaphysics. -- Hobbes
I've gone through it very quickly, just looking at the stuff marked
by change bars.
It appears that the change bars mark differences from n1256.pdf (i.e.,
from C99 + TC1 + TC2 + TC3). Is that correct?
Most of the changes have to do with a clearer presentation of the
rules for sequence points, particularly in 5.1.2.3. I haven't had
time to study it in depth, but I think it's clearer and less ambiguous
than the existing wording. One interesting glitch is this wording:
_Sequenced before_ is an asymmetric, transitive, pair-wise
relation between evaluations executed by a single thread, which
induces a partial order among those evaluations.
This is the only use of the word "thread" in the entire document. Are
there plans to define and discuss threads in more depth?
Also, the section on type specifiers (6.7.2) refers to "void", "char",
"signed char" and so forth as "multisets" rather than "sets", allowing
for "long long", clearing up an ambiguity that was recently discussed
here at considerable length. (It still refers to the groups of
multisets as "lines", even though one of them extends over two lines;
as long as you're cleaning up the wording you might want to fix that
as well.)
There have been rumors about some C99-specific features being dropped;
there's no sign of that here.
I understand this is a work in progess, but I'll mention one item on
my wish list: perhaps it's time to make one more attempt to construct
a coherent definition of "lvalue". Ok, two items: the definition of
"expression" could use some cleaning up as well. (Taking the current
wording literally, 42 is not an expression, but if we assume that it
is an expression then it's an lvalue, but any attempt to use it
invokes undefined behavior. I'm going to assume that wasn't the
intent.)
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Yes; I suspect that from now on the diff marks will be against the
previous draft rather than against any fixed base document.
> Most of the changes have to do with a clearer presentation of the
> rules for sequence points, particularly in 5.1.2.3.
The changes are the ones approved at the previous meeting (consult the
minutes in N1300 for details). Anyone interested in the kinds of things
currently being considered should look at the documents posted on the
committee's web site:
<http://www.open-std.org/jtc1/sc22/wg14/www/documents>
> I haven't had
> time to study it in depth, but I think it's clearer and less ambiguous
> than the existing wording. One interesting glitch is this wording:
>
> _Sequenced before_ is an asymmetric, transitive, pair-wise
> relation between evaluations executed by a single thread, which
> induces a partial order among those evaluations.
>
> This is the only use of the word "thread" in the entire document. Are
> there plans to define and discuss threads in more depth?
Yes (see, for example, N1325 and N1329).
> Also, the section on type specifiers (6.7.2) refers to "void", "char",
> "signed char" and so forth as "multisets" rather than "sets", allowing
> for "long long", clearing up an ambiguity that was recently discussed
> here at considerable length. (It still refers to the groups of
> multisets as "lines", even though one of them extends over two lines;
> as long as you're cleaning up the wording you might want to fix that
> as well.)
Noted.
> There have been rumors about some C99-specific features being dropped;
> there's no sign of that here.
As far as I know, no one has made any concrete proposals along those
lines.
> I understand this is a work in progess, but I'll mention one item on
> my wish list: perhaps it's time to make one more attempt to construct
> a coherent definition of "lvalue". Ok, two items: the definition of
> "expression" could use some cleaning up as well. (Taking the current
> wording literally, 42 is not an expression, but if we assume that it
> is an expression then it's an lvalue, but any attempt to use it
> invokes undefined behavior. I'm going to assume that wasn't the
> intent.)
I'm open to suggestions -- if comp.std.c can come up with definitions
that are generally agreed to be correct, I can almost certainly get them
in.
--
Larry Jones
Yep, we'd probably be dead by now if it wasn't for Twinkies. -- Calvin
Both issues have been discussed here before, but I'll give it another
shot. I don't expect to be able to come up with acceptable
standardese wording on the first try.
(Throughout this article, I use underscores to denote italics and
curly braces to denote text that I've added.)
The C90 standard's definition of "lvalue" was flawed. C90 6.2.2.1:
An _lvalue_ is an expression (with an object type or an incomplete
type other than void) that designates an object.
The problem with that was that whether a given expression designates
an object can depend on the run-time value of the expression. The
name of a pointer object may or may not designate an object, depending
on its current value -- but clearly we want it to be an lvalue
regardless of its current value.
C99 attempted to fix this. C99 6.3.2.1p1:
An _lvalue_ is an expression with an object type or an incomplete
type other than void; if an lvalue does not designate an object
when it is evaluated, the behavior is undefined.
This goes too far in the other direction; it includes expressions that
*cannot* designate objects. 42, for example, is an expression with an
object type. And if the expression 42 is evaluated, since it does not
designate an object, the behavior is undefined. Likewise, if ptr is a
pointer object whose current value is a null pointer, and assuming the
expression ``ptr'' is an lvalue, then evaluating the expression
``ptr'' invokes undefined behavior since it doesn't currently
designate an object. The behavior should be undefined only if it's
evaluated *as an lvalue*.
My suggestion:
An _lvalue_ is an expression with an object type or an incomplete
type other than void that {potentially} designates an object{.}
If an lvalue does not {actually} designate an object when it is
evaluated {in a context that requires an lvalue}, the behavior is
undefined.
with a footnote:
An expression _potentially designates_ an object either if it
designates an object, or if it could do so given appropriate
values for the expression or any subexpressions. For example,
given:
int *ptr = NULL;
the expression ``ptr'' _potentially designates_ an object of type
int, even if it never actually does so during the execution of
the program.
I'd prefer to have a more rigorous definition of "potentially
designates" so this needn't be relegated to a footnote with an
example, but I haven't been able to come with anything better than
this.
As for "expression", the definition didn't change from C90 to C99.
C99 6.5p1:
An _expression_ is a sequence of operators and operands that
specifies computation of a value, or that designates an object or
a function, or that generates side effects, or that performs a
combination thereof.
The intent is clear enough, I suppose, but a literal reading implies
that 42 isn't an expression, since there is no operator, and without
an operator there can't be an operand.
It's been argued that 42 is the operand of an invisible operator, but
that's not convincing unless the language actually defines such an
operator.
The expressions that are left out of the current definition are the
primary-expressions: identifiers, constants, string-literals, and
parenthesized expressions (since parentheses aren't an operator).
Also, the use of plurals could imply to the tediously literal-minded
that there must be at least two operators and at least two operands.
The term "expression" is correctly and rigorously defined by the
grammar. 6.5p1 could just say that an expression is a construct that
satisfies the grammar for "expression", but that's unsatisfying; I
think we want the English-language definition to illuminate what
expressions are for.
Here's my proposal:
An _expression_ is a sequence of {one or more} operators,
operands, {and _primary-expression_s} that specifies computation
of a value, or that designates an object or a function, or that
generates side effects, or that performs a combination thereof.
I'm not entirely happy with the need to use the syntactic category
"primary-expression" in the definition of "expression".
No. The name of a pointer object always designates that pointer object,
regardless of its value. (Similarly, the name of an int object always
designates the named int object.)
> C99 attempted to fix this. C99 6.3.2.1p1:
>
> An _lvalue_ is an expression with an object type or an incomplete
> type other than void; if an lvalue does not designate an object
> when it is evaluated, the behavior is undefined.
>
> This goes too far in the other direction; it includes expressions that
> *cannot* designate objects. 42, for example, is an expression with an
> object type. And if the expression 42 is evaluated, since it does not
> designate an object, the behavior is undefined.
Obviously, the intent was not to say that the expression 42 is an lvalue or
that its behaviour is undefined.
> Likewise, if ptr is a
> pointer object whose current value is a null pointer, and assuming the
> expression ``ptr'' is an lvalue, then evaluating the expression
> ``ptr'' invokes undefined behavior since it doesn't currently
> designate an object. The behavior should be undefined only if it's
> evaluated *as an lvalue*.
No, the expression "ptr" always designates the object ptr, regardless of
whether the value of that object points to some object, is a null pointer,
or is indeterminate.
> My suggestion:
>
> An _lvalue_ is an expression with an object type or an incomplete
> type other than void that {potentially} designates an object{.}
> If an lvalue does not {actually} designate an object when it is
> evaluated {in a context that requires an lvalue}, the behavior is
> undefined.
As far as I can tell, the only way to have an lvalue expression that doesn't
designate an object is by trying to dereference a pointer that doesn't point
to an object. The words about the behaviour being undefined in those
situations belong in the descriptions of operators that dereference
pointers, rather than in the definition of lvalue. The expression ptr[0] is
an lvalue expression, and the expression 42/x is an rvalue expression, even
if ptr is a null pointer or x is zero.
(The reason I say "lvalue expression" rather than just "lvalue" is because
even though the standard seems to define the word "lvalue" to be an
expression, it often uses the word to talk about the result produced by
evaluating such en expression rather than to the expression itself -- for
instance, it says that the *result* of the unary * operator is "an lvalue
designating the object". That's a little sloppy: obviously, the result of
an operator is not another expression. Perhaps the standard needs a
distinction between an "lvalue expression" (a sequence of tokens that
designates an object when evaluated) and an "lvalue" (the "designation" of
an object produced by evaluating an lvalue expression), similar to the
distinction between an "rvalue expression" (i.e. an expression that is not
an lvalue expression) and an "rvalue" (also known as a "value").)
> with a footnote:
>
> An expression _potentially designates_ an object either if it
> designates an object, or if it could do so given appropriate
> values for the expression or any subexpressions.
> For example,
> given:
> int *ptr = NULL;
> the expression ``ptr'' _potentially designates_ an object of type
> int, even if it never actually does so during the execution of
> the program.
No, the expression "ptr" designates an object of type int* (the pointer
variable named "ptr"). The value stored in that object may *point* to (not
*designate*, because it's not an lvalue) some object, or just past the end
of some array, or be a null pointer, or be indeterminate.
The expression *ptr designates an object of type int, unless undefined
behaviour has been invoked, for instance by applying the * operator to a
null pointer or a pointer to past the end of an array, or by trying to
convert the lvalue "ptr" to a value when the designated object (the variable
named "ptr") had an indeterminate value.
...
> The term "expression" is correctly and rigorously defined by the
> grammar. 6.5p1 could just say that an expression is a construct that
> satisfies the grammar for "expression", but that's unsatisfying; I
> think we want the English-language definition to illuminate what
> expressions are for.
Right; 6.5p1 is more of an explanation than a real definition in the
matematical sense. The text would be made clearer by turning that sentence
into a footnote.
The distinction between lvalue and rvalue expressions could be defined by
the syntax, too, possibly with a little help of English prose where the
distinction depends on the types of operands.
> For anyone who's interested, the very first draft for the C1X standard
> is now available from the committee's web site:
>
> <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1336.pdf>
Thank you very much for that. Like Keith, I did only a very quick
skim for the change bars, and I will need to spend more time with it
in the future.
One question comes to mind, however. Since the we're now talking C1X
rather than C0X, is there any ETA available? A range, if not a
specific year?
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
Whoops. Sorry, what I meant to say was that the expression ``*ptr''
is an lvalue regardless of the current value of ptr.
>> C99 attempted to fix this. C99 6.3.2.1p1:
>>
>> An _lvalue_ is an expression with an object type or an incomplete
>> type other than void; if an lvalue does not designate an object
>> when it is evaluated, the behavior is undefined.
>>
>> This goes too far in the other direction; it includes expressions that
>> *cannot* designate objects. 42, for example, is an expression with an
>> object type. And if the expression 42 is evaluated, since it does not
>> designate an object, the behavior is undefined.
>
> Obviously, the intent was not to say that the expression 42 is an
> lvalue or that its behaviour is undefined.
Obviously. I'm trying to contruct wording that expresses the actual
intent.
>> Likewise, if ptr is a
>> pointer object whose current value is a null pointer, and assuming the
>> expression ``ptr'' is an lvalue, then evaluating the expression
>> ``ptr'' invokes undefined behavior since it doesn't currently
>> designate an object. The behavior should be undefined only if it's
>> evaluated *as an lvalue*.
>
> No, the expression "ptr" always designates the object ptr, regardless
> of whether the value of that object points to some object, is a null
> pointer, or is indeterminate.
Again, I meant *ptr, not ptr. (*sigh*)
>> My suggestion:
>>
>> An _lvalue_ is an expression with an object type or an incomplete
>> type other than void that {potentially} designates an object{.}
>> If an lvalue does not {actually} designate an object when it is
>> evaluated {in a context that requires an lvalue}, the behavior is
>> undefined.
>
> As far as I can tell, the only way to have an lvalue expression that
> doesn't designate an object is by trying to dereference a pointer that
> doesn't point to an object. The words about the behaviour being
> undefined in those situations belong in the descriptions of operators
> that dereference pointers, rather than in the definition of lvalue.
> The expression ptr[0] is an lvalue expression, and the expression 42/x
> is an rvalue expression, even if ptr is a null pointer or x is zero.
Similarly, arr[20] is an lvalue even if arr has only 10 elements --
which is just another case of a pointer value that doesn't point to an
object.
I think I agree that the undefined behavior should be specified in the
description of the unary "*" operator, not in the definition of
"lvalue".
> (The reason I say "lvalue expression" rather than just "lvalue" is
> because even though the standard seems to define the word "lvalue" to
> be an expression, it often uses the word to talk about the result
> produced by evaluating such en expression rather than to the
> expression itself -- for instance, it says that the *result* of the
> unary * operator is "an lvalue designating the object". That's a
> little sloppy: obviously, the result of an operator is not another
> expression. Perhaps the standard needs a distinction between an
> "lvalue expression" (a sequence of tokens that designates an object
> when evaluated) and an "lvalue" (the "designation" of an object
> produced by evaluating an lvalue expression), similar to the
> distinction between an "rvalue expression" (i.e. an expression that is
> not an lvalue expression) and an "rvalue" (also known as a "value").)
Perhaps this is because the original (pre-C) meaning of "lvalue" was
different than what the C standard settled on. The idea was that an
expression could be evaluated for its "rvalue" (what C calls the value
of the expression), or, for some expressions, for its "lvalue", which
is the identity of the object that it designates.
>> with a footnote:
>>
>> An expression _potentially designates_ an object either if it
>> designates an object, or if it could do so given appropriate
>> values for the expression or any subexpressions.
>> For example,
>> given:
>> int *ptr = NULL;
>> the expression ``ptr'' _potentially designates_ an object of type
>> int, even if it never actually does so during the execution of
>> the program.
>
> No, the expression "ptr" designates an object of type int* (the
> pointer variable named "ptr"). The value stored in that object may
> *point* to (not *designate*, because it's not an lvalue) some object,
> or just past the end of some array, or be a null pointer, or be
> indeterminate.
Right.
> The expression *ptr designates an object of type int, unless undefined
> behaviour has been invoked, for instance by applying the * operator to
> a null pointer or a pointer to past the end of an array, or by trying
> to convert the lvalue "ptr" to a value when the designated object (the
> variable named "ptr") had an indeterminate value.
Right.
> ...
>> The term "expression" is correctly and rigorously defined by the
>> grammar. 6.5p1 could just say that an expression is a construct that
>> satisfies the grammar for "expression", but that's unsatisfying; I
>> think we want the English-language definition to illuminate what
>> expressions are for.
>
> Right; 6.5p1 is more of an explanation than a real definition in the
> matematical sense. The text would be made clearer by turning that
> sentence into a footnote.
>
> The distinction between lvalue and rvalue expressions could be defined
> by the syntax, too, possibly with a little help of English prose where
> the distinction depends on the types of operands.
--
> lawrenc...@siemens.com writes:
> > Keith Thompson <ks...@mib.org> wrote:
> [...]
> >> I understand this is a work in progess, but I'll mention one item on
> >> my wish list: perhaps it's time to make one more attempt to construct
> >> a coherent definition of "lvalue". [snip]
> >
> > I'm open to suggestions -- if comp.std.c can come up with definitions
> > that are generally agreed to be correct, I can almost certainly get them
> > in.
>
> [snip] C99 6.3.2.1p1:
>
> An _lvalue_ is an expression with an object type or an incomplete
> type other than void; if an lvalue does not designate an object
> when it is evaluated, the behavior is undefined.
I suggest:
An _lvalue_ is an expression with an object type or an incomplete
type other than void, and whose form indicates that it might be
used to designate an object; which forms of expression correspond
to lvalues is specified later, in subclauses of 6.5. If an lvalue
does not designate an object when it is evaluated, the behavior is
undefined.
The subclauses are 6.5.1, (perhaps) 6.5.2.1, 6.5.2.3, 6.5.2.5, 6.5.3.2.
identifier and (lvalue) 6.5.1
array indexing 6.5.2.1
. and -> 6.5.2.3
compound literals 6.5.2.5
* 6.5.3.2
The lvalue-ness for array indexing might be inferred by its equivalent
expression in terms of the * operator. 6.5.2.1p2 doesn't mention
lvalue-ness now, but I think it would be good if it did (perhaps
in a footnote).
Incidentally the current index entry for lvalue seems to be missing
some references; it lists only 6.3.2.1, 6.5.1, 6.5.2.4, 6.5.3.1,
and 6.5.16. (The entry for _modifiable lvalue_ lists only 6.3.2.1.)
Also, to keep usage consistent, the paragraph n1336 6.3.2.1p2:
Except when it is the operand of the sizeof operator, the unary &
operator, the ++ operator, the -- operator, or the left operand of
the . operator or an assignment operator, an lvalue that does not
have array type is converted to the value stored in the designated
object (and is no longer an lvalue).
might be revised to
Except when it is the operand of the sizeof operator, the unary &
operator, the ++ operator, the -- operator, or the left operand of
the . operator or an assignment operator, an lvalue that does not
have array type represents an expression that implicitly converts
the designated object into the value stored in that object (and
this implied expression is not an lvalue).
> My suggestion:
>
> An _lvalue_ is an expression with an object type or an incomplete
> type other than void that {potentially} designates an object{.}
> If an lvalue does not {actually} designate an object when it is
> evaluated {in a context that requires an lvalue}, the behavior is
> undefined.
>
> with a footnote:
>
> An expression _potentially designates_ an object either if it
> designates an object, or if it could do so given appropriate
> values for the expression or any subexpressions. For example,
> given:
> int *ptr = NULL;
> the expression ``ptr'' _potentially designates_ an object of type
> int, even if it never actually does so during the execution of
> the program.
>
> I'd prefer to have a more rigorous definition of "potentially
> designates" so this needn't be relegated to a footnote with an
> example, but I haven't been able to come with anything better than
> this.
I like this general approach, but as you point out the notion of
_potentially designates_ seems hard to define rigorously. After
thinking about it, it struck me that some forms of expression can
be used to designate objects, and other forms of expression cannot
(regardless of whether they might actually designate them in
some program run). Hence, the phrasing suggested above.
> [snip]
>
> As far as I can tell, the only way to have an lvalue expression that doesn't
> designate an object is by trying to dereference a pointer that doesn't point
> to an object. The words about the behaviour being undefined in those
> situations belong in the descriptions of operators that dereference
> pointers, rather than in the definition of lvalue. The expression ptr[0] is
> an lvalue expression, and the expression 42/x is an rvalue expression, even
> if ptr is a null pointer or x is zero.
>
> (The reason I say "lvalue expression" rather than just "lvalue" is because
> even though the standard seems to define the word "lvalue" to be an
> expression, it often uses the word to talk about the result produced by
> evaluating such en expression rather than to the expression itself -- for
> instance, it says that the *result* of the unary * operator is "an lvalue
> designating the object". That's a little sloppy: obviously, the result of
> an operator is not another expression. Perhaps the standard needs a
> distinction between an "lvalue expression" (a sequence of tokens that
> designates an object when evaluated) and an "lvalue" (the "designation" of
> an object produced by evaluating an lvalue expression), similar to the
> distinction between an "rvalue expression" (i.e. an expression that is not
> an lvalue expression) and an "rvalue" (also known as a "value").)
Certainly the principle here is sound; the usage should be consistent.
I think I would advocate that the term "lvalue" still be defined
to mean certain forms of expression, and other uses be brought
into line with that choice. My reasoning is that it is both
closer to the existing writing, and also an easier sell to the
committee, since it's a smaller change. I admit I haven't looked
closely at all the existing uses (although I did at the two
paragraphs shown in my earlier suggestion). In any case, I agree
that other uses should be consistent with whatever definition is
finally settled on (although, it doesn't seem to. bad now, not
counting the main problem with the definitional text itself).
As per N1250 (The C1X Charter, which I highly recommend reading), the
target date for a published standard is 2012.
--
Larry Jones
I obey the letter of the law, if not the spirit. -- Calvin
But what did you mean by the "as an lvalue" part? An lvalue expression is
always evaluated as an lvalue. Depending on the context, it might *then*
undergo the implicit conversion to an rvalue, but anything that triggers
undefined behaviour during the evaluation "as an lvalue" triggers it
regardless of whether the context then calls for the implicit conversion or
not. There might be cases where an expression has undefined behaviour only
when evaluated "as an rvalue", but not the other way around.
...
>> As far as I can tell, the only way to have an lvalue expression that
>> doesn't designate an object is by trying to dereference a pointer that
>> doesn't point to an object. The words about the behaviour being
>> undefined in those situations belong in the descriptions of operators
>> that dereference pointers, rather than in the definition of lvalue.
>> The expression ptr[0] is an lvalue expression, and the expression 42/x
>> is an rvalue expression, even if ptr is a null pointer or x is zero.
>
> Similarly, arr[20] is an lvalue even if arr has only 10 elements --
> which is just another case of a pointer value that doesn't point to an
> object.
Not any more than arr[1/0] is. Both are expressions that trigger undefined
behaviour before they have a chance to produce a pointer value.
> I think I agree that the undefined behavior should be specified in the
> description of the unary "*" operator, not in the definition of
> "lvalue".
There also is the complication of a unary "&" cancelling a unary "*". The
expression &*ptr has a defined behaviour even if ptr is a null pointer and
the lvalue subexpression *ptr does not designate an object. It feels wrong
when the description of an operator overrides a definition, doesn't it?
Oh, and another one (and this one is messy) -- rvalue arrays:
struct foo { int v, a[1]; } x, y, fun();
int *p = & ( x = y ).v; // Invalid, the argument of the & is not an
lvalue
int *q = & ( x = y ).a[0]; // Valid according to C99, but what does q
point to: x.a[0], y.a[0], or something else?
int *r = fun().a; // How about here?
I think I was just being temporarily stupid. The distinction between
evaluating something as an lvalue and as a non-lvalue would be
important if we kept the existing C99 definition of "lvalue", but the
whole point is that we (well, I) want to revise the definition so it
describes only things that really are lvalues.
Give me a little time and I'll take a second stab at this. It might
turn out to be simpler than I had thought. Though there's still the
problem of constructing a definition that includes both *ptr when ptr
points to an object and *ptr when ptr doens't point to an object,
while excluding 42.
> ...
>>> As far as I can tell, the only way to have an lvalue expression that
>>> doesn't designate an object is by trying to dereference a pointer that
>>> doesn't point to an object. The words about the behaviour being
>>> undefined in those situations belong in the descriptions of operators
>>> that dereference pointers, rather than in the definition of lvalue.
>>> The expression ptr[0] is an lvalue expression, and the expression 42/x
>>> is an rvalue expression, even if ptr is a null pointer or x is zero.
>>
>> Similarly, arr[20] is an lvalue even if arr has only 10 elements --
>> which is just another case of a pointer value that doesn't point to an
>> object.
>
> Not any more than arr[1/0] is. Both are expressions that trigger
> undefined behaviour before they have a chance to produce a pointer
> value.
Right again. I think I haven't been drinking enough coffee.
>> I think I agree that the undefined behavior should be specified in the
>> description of the unary "*" operator, not in the definition of
>> "lvalue".
>
> There also is the complication of a unary "&" cancelling a unary "*".
> The expression &*ptr has a defined behaviour even if ptr is a null
> pointer and the lvalue subexpression *ptr does not designate an
> object. It feels wrong when the description of an operator overrides
> a definition, doesn't it?
Yeah, that's a special-case rule that makes things more complicated.
It's an exception to the rule that the evaluation of an expression
isn't affected by the context in which it appears (there may be other
exceptions to that as well).
> Oh, and another one (and this one is messy) -- rvalue arrays:
>
> struct foo { int v, a[1]; } x, y, fun();
>
> int *p = & ( x = y ).v; // Invalid, the argument of the & is not an
> lvalue
> int *q = & ( x = y ).a[0]; // Valid according to C99, but what does
> q point to: x.a[0], y.a[0], or something else?
> int *r = fun().a; // How about here?
Ah, but rvalue arrays are going away! See n1336 6.2.4p7:
A non-lvalue expression with structure or union type, where the
structure or union contains a member with array type (including,
recursively, members of all contained structures and unions)
refers to an object with automatic storage duration and temporary
lifetime. Its lifetime begins when the expression is evaluated
and its initial value is the value of the expression. Its lifetime
ends when the evaluation of the containing full expression or full
declarator ends. Any attempt to modify an object with temporary
lifetime results in undefined behavior.
with a footnote:
The address of such an object is taken implicitly when an array
member is accessed
Is it possible to search for change bars? Or color-highlight them or
something? (I'm on Linux, if that makes a difference.)
--
Hallvard
I don't see a way to do so using Adobe Reader under Windows.
Incidentally, I just noticed something else about the formatting. A
'*' in the right margin, where a change bar would be, denotes deleted
text. For example, n1256.pdf 6.5.2.2p5 is:
If the expression that denotes the called function
has type pointer to function returning an object type,
the function call expression has the same type as that
object type, and has the value determined as specified in
6.8.6.4. Otherwise, the function call has type void. If
an attempt is made to modify the result of a function
call or to access it after the next sequence point,
the behavior is undefined.
whereas the same paragraph in n1336.pdf is:
If the expression that denotes the called function
has type pointer to function returning an object type,
the function call expression has the same type as that
object type, and has the value determined as specified
in 6.8.6.4. Otherwise, the function call has type void. *
FWIW, I've seen drafts of the Ada standard that use a strikeout markup
for deleted text and underlining for new text.
One quick question:
Seeing as gets() is obsolescent and is deprecated, why is its function
still defined? 7.19.7.7 should be removed, or changed to simply say
"The gets function is obsolescent and deprecated".
--
Ian Collins.
> Jack Klein <jack...@spamcop.net> wrote:
> >
> > One question comes to mind, however. Since the we're now talking C1X
> > rather than C0X, is there any ETA available? A range, if not a
> > specific year?
>
> As per N1250 (The C1X Charter, which I highly recommend reading), the
> target date for a published standard is 2012.
Thanks again, I hadn't seen that before.
If I could make one suggestion about the standardization process,
which you might be in a unique position to champion, it would be
replacing Microsoft Word format (of which there is no single such
thing), with the ISO Standard Open Document Format.
Too much to hope for, I suppose.
Ah, thanks for the good news. :)
Obsolescent and deprecated items are still present in the standard (or it
couldn't say they are), and so they are required to be properly
implemented by any conforming implementation. They cannot be properly
implemented if the standard doesn't define the behaviour. So either the
gets function's description is required, or no mention to gets should be
made at all, especially not to say it is obsolescent and/or deprecated.
And personally, I doubt gets will be removed so shortly after its
deprecation.
I proposed a year ago a
Obsolescent and Deprecated features
section, in the form of some Appendix. That would be
non-normative and would satisfy the requirements of
defining those features.
But that it is too much work for the committee.
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
This?
http://groups.google.com/group/comp.std.c/msg/522c1231b2ccd6f3
> That would be non-normative and
> would satisfy the requirements of defining those features.
Firstly, no, it would not satisfy the requirements. If the definition is
non-normative, all requirements of the standard will be met if an
incompatible definition is used by the implementation. In other words, if
the definition is non-normative, it isn't a definition at all.
Secondly, if a function such as gets is removed from the normative text of
the standard, conforming implementations are no longer allowed to declare
it in <stdio.h>.
Since those features are deprecated this doesn't hurt.
Compilers that define gets() differently (taking one more argument
for instance) would be OK.
Why would anybody bother?
> Secondly, if a function such as gets is removed from the normative text of
> the standard, conforming implementations are no longer allowed to declare
> it in <stdio.h>.
Exactly. If you want gets() you would have to include the
header
<obsolete.h>
Why this would be a problem?
Is there some reason I'm missing that gets is present in the current
standard other than to avoid breaking existing programs?
Wouldn't that be a good thing?
--
Ian Collins.
No. It may be a good thing if gets is removed completely from the
standard, but if it's kept in, there's no benefit in moving it to another
header.
You miss the point. Since the time that the committee decided to
deprecate gets(), there has not yet been an official version of the
standard published - this upcoming version will be the one in which it
is deprecated. Deprecation means the feature is still fully supported
and mandatory, but may be removed from some future standard. There has
to be at least one actual published standard which still mandates
support for gets(), or the correct word would not be "deprecated", the
correct word would be "removed". Making it a non-mandatory feature has
the same effect, as far as the standard is concerned, as removing it
completely.
You may argue that gets() should simply be removed, and not pass through
any intermediate stage of being deprecated. Go ahead and argue it - but
until you've convinced the committee otherwise, you'll have to settle
for deprecation.
As any anti-gets fanatic will tell you, those programs are already broken,
and the only reason gets is still present is because the committee is too
lazy to remove it. :-/
OK
> Deprecation means the feature is still fully supported
> and mandatory, but may be removed from some future standard.
OK. Then the Appendix X: Obsolete and deprecated features
is normative.
It defines the standard header:
<obsolete.h>
In this appendix we have all functions that were declared obsolescent
or deprecated in previous standards.
> There has
> to be at least one actual published standard which still mandates
> support for gets(), or the correct word would not be "deprecated", the
> correct word would be "removed".
OK. Correct. The deprecated appendix has to be normative.
> Making it a non-mandatory feature has
> the same effect, as far as the standard is concerned, as removing it
> completely.
>
OK
> You may argue that gets() should simply be removed, and not pass through
> any intermediate stage of being deprecated. Go ahead and argue it - but
> until you've convinced the committee otherwise, you'll have to settle
> for deprecation.
1) An appendix with obsolete and deprecated features is not only for
gets. We could put there several other functions like asctime(),
for instance. And surely the definitions of trigraphs belongs THERE.
2) This would create a standard way of deprecating features.
Nitpick: that should say "previous versions of this standard".
Note: with that description, <obsolete.h> will not declare gets(), since
no previous versions of the standard has yet declared it deprecated.
The title you've given to your proposed Appendix X implies that it will
describe not only features that have been deprecated in previous
versions of the standard, but that it will also contain features that
are still deprecated in the current version. In other words, features
that have not yet actually been removed from the standard. If this is
your intent, I doubt that the committee would accept it. It implies that
the committee is encouraging a three-step removal process. In step 1, a
feature is marked as deprecated. In a later version of the standard, it
may still be deprecated, but if so it is now moved to <obsolete.h>,
requiring those who still wish to use it to add a line
"#include <obsolete.h>"
to the files where that feature is used. Then, in yet another version of
the standard, the feature is finally removed. Any code still depending
upon that feature must be modified to remove that dependence before
compilers implementing that third version of the standard become
commonplace.
The committee currently has only a two-step process: in one version of
the standard, a feature is marked as deprecated, which means that any
code which relies upon it can continue to do so without requiring any
modification, but that such code should have that dependence removed
before compilers implementing the next version of the standard become
commonplace. In some later version of the standard, the feature is
actually removed. Unlike your suggestion, there's no intermediate phase
where people can continue to use it, but only at the expense of
modifying their code. I doubt that there's anyone so in love with gets()
that they actually want to draw out it's death over three different
versions of the standard.
...
> 2) This would create a standard way of deprecating features.
>
There is already a standard way of deprecating features. It involves
saying that they are deprecated in the text of the description of the
feature. Offhand, I don't see any need to make the process more
complicated or slower.
jacob, suppose, hypothetically, that somebody told you that your
lcc-win compiler *still* doesn't implement the entire C99 standard,
that this has been pointed out to you for *years*, and that (drum
roll, please) apparently this is *too much work* for you.
Would that motivate you to finish the implementation? Or would you be
pissed off because you've just been insulted yet again?
What makes you think that insults (yes, I'd consider "But that it is
too much work for the committee." to be an insult) will motivate the C
committee any better than they'd motivate you, or anyone else?
(Let me be clear: this really is hypothetical. I'm *not* accusing you
of laziness, just making a point.)
Also, n1336.pdf is the *first* *preliminary* *draft* of the new C1X
standard. It's basically n1256 with just a few changes, specifically
the ones that the committee has gotten around to working on so far.
They don't have infinite time or resources. And there's no particular
reason why changes that you consider most important, or even changes
*they* consider most important, should be the first ones they work on.
Even assuming that, for example, asctime() MUST BE FIXED, the fact
that there are no changes to asctime() in this first draft means
nothing, regardless of how strongly jacob navia feels about it.
You might also consider that the committee's failure to implement
something you've proposed might have explanations other than laziness.
Maybe they just don't like your idea.
Mr Plauger, a committee member, said in this group that
fixing asctime() is too much work:
Last time we discussed this (June 2004) I proposed that
asctime() returns NULL.
<jacob navia>
> What does it cost to you just choose a simple wording like:
> "If the day/month/year/ in the structure tm passed to asctime
> is out of range, a NULL value will be returned, and errno will
> be set accordingly" (ERANGE I suppose).
</jacob navia>
<Plauger>
Don't cost me squat. But it costs my customers a *huge* amount
to go through code written over the past third of a century and
add checks for null pointer returns. That'll never happen.
Well, actually it does cost me and my fellow committee members
something. I'd guess about a half hour out of our lives dealing
with yet another DR. Plus another hour of cumulative Benito
time and Jones time doing bookkeeping, proofreading, and
editing. Maybe that sounds cheap to you, but I'm talking time
that's precious to me and other committee members because it
involves us getting together somewhere in the world and
focusing intently for a week on a broad assortment of esoteric
issues. Triage really means something under those circumstances.
</Plauger >
A few hours since 2004 have been impossible to find.
Compare that to the boatload of features of C99 I have implemented
in this 4 years.
> Keith Thompson wrote:
>>
>> What makes you think that insults (yes, I'd consider "But that it is
>> too much work for the committee." to be an insult) will motivate the C
>> committee any better than they'd motivate you, or anyone else?
>>
>
> Mr Plauger, a committee member, said in this group that
> fixing asctime() is too much work:
Your current claim is that your feature deprecation mechanism was too
much work for the committee. The response of one member of the
committee to a bad proposal for fixing asctime has no bearing on that
claim.
> Last time we discussed this (June 2004) I proposed that
> asctime() returns NULL.
>
> <jacob navia>
>> What does it cost to you just choose a simple wording like:
>
>> "If the day/month/year/ in the structure tm passed to asctime
>> is out of range, a NULL value will be returned, and errno will
>> be set accordingly" (ERANGE I suppose).
> </jacob navia>
I would be furious at this, though I would try to hide it. "Just
choose a simple wording" -- standards are easy. A few keystrokes and
problem solved. Who cares about all the code that needs to be
re-written? Who cares if the words are vague and open to several
interpretations? By writing this short paragraph you would have lost
any chance of my taking you seriously if I had the misfortune to be a
committee member (it is a thankless task).
> <Plauger>
> Don't cost me squat. But it costs my customers a *huge* amount
> to go through code written over the past third of a century and
> add checks for null pointer returns. That'll never happen.
>
> Well, actually it does cost me and my fellow committee members
> something. I'd guess about a half hour out of our lives dealing
> with yet another DR. Plus another hour of cumulative Benito
> time and Jones time doing bookkeeping, proofreading, and
> editing. Maybe that sounds cheap to you, but I'm talking time
> that's precious to me and other committee members because it
> involves us getting together somewhere in the world and
> focusing intently for a week on a broad assortment of esoteric
> issues. Triage really means something under those circumstances.
>
> </Plauger >
>
> A few hours since 2004 have been impossible to find.
I would not spend a second on that proposal. It is poorly worded and
is likely to require a rewrite of existing code. Plauger's remark
about triage is simply saying that the non-starters have to be weeded
out early. What is the point of doing any of the paperwork for an
idea that has no hope of getting through?
> Compare that to the boatload of features of C99 I have implemented
> in this 4 years.
Plauger et. al. have, quite probably, been doing lots of other stuff
as well.
--
Ben.
jacob navia wrote:
> A few hours since 2004 have been impossible to find.
>
> Compare that to the boatload of features of C99 I have implemented
> in this 4 years.
Be part of the committee directly by being there and
contributing the 2 weeks a year for meetings and
1 to 2 times more for preparation and writing white
papers.
It is the opportunity to make good ideas happen and
kill bad ones.
Walter Banks
No, I just said that fixing asctime() is apparently too
much work since the new document contains the
same buffer overflow bug.
> The response of one member of the
> committee to a bad proposal for fixing asctime has no bearing on that
> claim.
>
Yes, my proposal is "bad". Better leave the bug there
without fixing it. That's surely a wonderful solution.
>> Last time we discussed this (June 2004) I proposed that
>> asctime() returns NULL.
>>
>> <jacob navia>
>>> What does it cost to you just choose a simple wording like:
>>> "If the day/month/year/ in the structure tm passed to asctime
>>> is out of range, a NULL value will be returned, and errno will
>>> be set accordingly" (ERANGE I suppose).
>> </jacob navia>
>
> I would be furious at this, though I would try to hide it.
Poor Becarisse. The things that make you "furious" are not
the same that make "ME" furious. I get angry at the committee
that after 8 years refuses to fix an obvious bug in the proposed
implementation of asctime(). THAT doesn't bother you at all.
What bothers you is that my wording wasn't in the required
legalese.
> "Just
> choose a simple wording" -- standards are easy. A few keystrokes and
> problem solved. Who cares about all the code that needs to be
> re-written?
You are talking nonsense (as usual). What code needs to be rewritten?
In what situation making the errors in asctime() explicit would
make some correct code obsolete?
> Who cares if the words are vague and open to several
> interpretations?
Which ones? How can you misinterpret
If the day/month/year in the structure tm passed
to asctime is out of range a NULL value will be
returned.
I do not understand how that can be interpreted in several ways.
The ranges are defined in the structure tm definition.
> By writing this short paragraph you would have lost
> any chance of my taking you seriously if I had the misfortune to be a
> committee member (it is a thankless task).
>
Happily you aren't, and I really do not care if you take me
seriously of course. Your standards are all legalese and
nothing to the current discussion: how to fix the buffer overflow
in the standard text. To THAT problem you do not say a single
word. Beating Jacob and defending the current bugs is FAR more
important to you than fixing any obvious bug.
>> <Plauger>
>> Don't cost me squat. But it costs my customers a *huge* amount
>> to go through code written over the past third of a century and
>> add checks for null pointer returns. That'll never happen.
>>
>> Well, actually it does cost me and my fellow committee members
>> something. I'd guess about a half hour out of our lives dealing
>> with yet another DR. Plus another hour of cumulative Benito
>> time and Jones time doing bookkeeping, proofreading, and
>> editing. Maybe that sounds cheap to you, but I'm talking time
>> that's precious to me and other committee members because it
>> involves us getting together somewhere in the world and
>> focusing intently for a week on a broad assortment of esoteric
>> issues. Triage really means something under those circumstances.
>>
>> </Plauger >
>>
>> A few hours since 2004 have been impossible to find.
>
> I would not spend a second on that proposal. It is poorly worded and
> is likely to require a rewrite of existing code.
You make assertions without ANY proof or hint of a proof.
You are totally wrong.
> Plauger's remark
> about triage is simply saying that the non-starters have to be weeded
> out early. What is the point of doing any of the paperwork for an
> idea that has no hope of getting through?
>
Yes. Let's leave the bug there. Who cares about C?
Plauger is in other standards committees (C++ I believe)
where he tries to do the job better than in the C committee where
any bug will be left there forever.
I do not have the budget to fly each year somewhere
in the world.
In this days of electronic communications it is
strange that we do not use it more, but that is the
fact.
>
>
> You are talking nonsense (as usual). What code needs to be rewritten?
> In what situation making the errors in asctime() explicit would
> make some correct code obsolete?
>
>
>> Who cares if the words are vague and open to several
>> interpretations?
>
> Which ones? How can you misinterpret
>
> If the day/month/year in the structure tm passed
> to asctime is out of range a NULL value will be
> returned.
>
The problem is in requiring that a conforming implementation return NULL
(yes they are allowed to currently if the result of the implementation
would be a buffer overflow, but they are not required to do this). Code
that currently fixes the problem in some other way (documented even
though that is not required) will now become non-conforming and code
written to that (documented) alternative solution becomes broken.
It is essential to distinguish between code that is essentially
non-portable (because it assumes some specific allowed solution) and
code that is inherently broken.
> Ben Bacarisse wrote:
>> jacob navia <ja...@nospam.com> writes:
>>
>>> Keith Thompson wrote:
>>>> What makes you think that insults (yes, I'd consider "But that it is
>>>> too much work for the committee." to be an insult) will motivate the C
>>>> committee any better than they'd motivate you, or anyone else?
>>>>
>>> Mr Plauger, a committee member, said in this group that
>>> fixing asctime() is too much work:
>>
>> Your current claim is that your feature deprecation mechanism was too
>> much work for the committee.
>
> No, I just said that fixing asctime() is apparently too
> much work since the new document contains the
> same buffer overflow bug.
No you said this:
| I proposed a year ago a
|
| Obsolescent and Deprecated features
|
| section, in the form of some Appendix. That would be
| non-normative and would satisfy the requirements of
| defining those features.
|
| But that it is too much work for the committee.
and, when challenged, cited the exchange with Plauger to back it up.
Re-opening the "they won't fix asctime" debate is a side-show to draw
attention away from this rather dismissive remark.
>> The response of one member of the
>> committee to a bad proposal for fixing asctime has no bearing on that
>> claim.
>>
>
> Yes, my proposal is "bad". Better leave the bug there
> without fixing it. That's surely a wonderful solution.
I am fed up with you putting words into my mouth. I contributed my
own preferred solution to this problem (not a good one I now
acknowledge) so it absurd to say I don't want it fixed. I don't think
this is problem you seem to think it is, but you are entitled to that
view.
>>> Last time we discussed this (June 2004) I proposed that
>>> asctime() returns NULL.
>>>
>>> <jacob navia>
>>>> What does it cost to you just choose a simple wording like:
>>>> "If the day/month/year/ in the structure tm passed to asctime
>>>> is out of range, a NULL value will be returned, and errno will
>>>> be set accordingly" (ERANGE I suppose).
>>> </jacob navia>
>>
>> I would be furious at this, though I would try to hide it.
>
> Poor Becarisse.
My name is Bacarisse. I am used to English people getting it wrong
but I find it ironic that you do. You've done it twice now so maybe
it is deliberate.
> The things that make you "furious" are not
> the same that make "ME" furious. I get angry at the committee
> that after 8 years refuses to fix an obvious bug in the proposed
> implementation of asctime(). THAT doesn't bother you at all.
Yet again, not what I said.
> What bothers you is that my wording wasn't in the required
> legalese.
No. My remark was conditional. I *would* be furious *if* I was one
of the people who would have to do the paperwork relating to a
non-starter of a proposal. I am not at all furious -- I am implicitly
commending Plauger on his restraint. I don't care about your wording
one way or the other.
>> "Just
>> choose a simple wording" -- standards are easy. A few keystrokes and
>> problem solved. Who cares about all the code that needs to be
>> re-written?
>
>
> You are talking nonsense (as usual). What code needs to be rewritten?
> In what situation making the errors in asctime() explicit would
> make some correct code obsolete?
Depending on what you mean by "out of range", yes. If you mean to
cover only those cases where the cited code produced UB, then your
wording is very bad. Even then some implementations may have dealt
with this matter in their own way and any code that has used such an
extension will have to re-written (or at least checked that it does
not need to be re-written).
>> Who cares if the words are vague and open to several
>> interpretations?
>
> Which ones? How can you misinterpret
Re-read the recent thread. There were several interpretations put on
what "out of range" might mean for struct tm values. You know what
you mean and presumably you think that is the only reasonable meaning,
but I don't know what you mean, even if you think it is obvious.
> If the day/month/year in the structure tm passed
> to asctime is out of range a NULL value will be
> returned.
>
> I do not understand how that can be interpreted in several ways.
> The ranges are defined in the structure tm definition.
Ah, if that is what you mean, then you should see that correct code
*will* need to be re-written. You seem to be holding conflicting
opinions here. The only meaning of "out of range" that would not
require code to be checked or re-written is the one proposed by Keith
Thompson -- exactly those values that cause the reference
implementation to exhibit UB. Having gone over this so recently in so
much detail I am surprised you don't see the problem.
>> By writing this short paragraph you would have lost
>> any chance of my taking you seriously if I had the misfortune to be a
>> committee member (it is a thankless task).
>>
>
> Happily you aren't, and I really do not care if you take me
> seriously of course. Your standards are all legalese and
> nothing to the current discussion: how to fix the buffer overflow
> in the standard text. To THAT problem you do not say a single
> word. Beating Jacob and defending the current bugs is FAR more
> important to you than fixing any obvious bug.
But that is not the current discussion. You were talking about a
deprecation mechanism and introduced this old canard when Keith
Thompson suggested that insulting the committee was unlikely to be
fruitful.
>>> <Plauger>
>>> Don't cost me squat. But it costs my customers a *huge* amount
>>> to go through code written over the past third of a century and
>>> add checks for null pointer returns. That'll never happen.
>>>
>>> Well, actually it does cost me and my fellow committee members
>>> something. I'd guess about a half hour out of our lives dealing
>>> with yet another DR. Plus another hour of cumulative Benito
>>> time and Jones time doing bookkeeping, proofreading, and
>>> editing. Maybe that sounds cheap to you, but I'm talking time
>>> that's precious to me and other committee members because it
>>> involves us getting together somewhere in the world and
>>> focusing intently for a week on a broad assortment of esoteric
>>> issues. Triage really means something under those circumstances.
>>>
>>> </Plauger >
>>>
>>> A few hours since 2004 have been impossible to find.
>>
>> I would not spend a second on that proposal. It is poorly worded and
>> is likely to require a rewrite of existing code.
>
> You make assertions without ANY proof or hint of a proof.
> You are totally wrong.
See above. All of the recent thread on this issue seems to have left
you uninformed about the details.
>> Plauger's remark
>> about triage is simply saying that the non-starters have to be weeded
>> out early. What is the point of doing any of the paperwork for an
>> idea that has no hope of getting through?
>
> Yes. Let's leave the bug there. Who cares about C?
Well I do and I am pretty sure Plauger does too.
> Plauger is in other standards committees (C++ I believe)
> where he tries to do the job better than in the C committee where
> any bug will be left there forever.
The phrase "not even wrong" comes to mind. By the way, C++ has
exactly the same "bug".
--
Ben.
jacob navia wrote:
> > Be part of the committee directly by being there and
> > contributing the 2 weeks a year for meetings and
> > 1 to 2 times more for preparation and writing white
> > papers.
> >
> > It is the opportunity to make good ideas happen and
> > kill bad ones.
> >
> > Walter Banks
> >
> >
>
> I do not have the budget to fly each year somewhere
> in the world.
>
> In this days of electronic communications it is
> strange that we do not use it more, but that is the
> fact.
There is plenty of electronic communications in WG-14
the final debate on ideas plays out over a few hours
instead of a months by face to face debate.
As a compiler vendor part of the cost of doing business
is representing your customers needs as part of international
standards. Providing criticism is one part (a part that you
have done well by the way) failure to advocate changes
fails to give direction and argument to the changes they
need.
w..
I don't have a copy on hand, but if IIRC, the C99 spec had a section
devoted to summarizing the changes from C89/C90. I don't see
anything similar in the new draft.
-drt
If you mean paragraph five of the Foreword, then as far as I can see,
n1336 still has it, but it is now paragraph seven of the Foreword with
paragraph six devoted for the changes from C99 to C1x (and empty at
this point in time.)
Correct: "|" indicates new or changed text, "*" deleted text. That's
how the traditional Unix diffmk program works, so I always just assume
that people will be familiar with it, but I really should add a quick
explanation to the Abstract.
--
Larry Jones
All this was funny until she did the same thing to me. -- Calvin
I've seen other documents use the same convention but it's hard to do
with troff and I think it makes the document hard to read and emphasizes
the wrong things.
--
Larry Jones
I've never seen a sled catch fire before. -- Hobbes
You mean in general? The C Standard is, and always has been, formatted
with troff (actually groff these days), not MS Word. I have no pull
whatsoever with ISO.
--
Larry Jones
I wonder if you can refuse to inherit the world. -- Calvin
Is it available in troff format ? Looking up stuff is much easier in a text
file.
--
Chqrlie.
santosh wrote:
> If you mean paragraph five of the Foreword, then as far as I can see,
> n1336 still has it, but it is now paragraph seven of the Foreword with
> paragraph six devoted for the changes from C99 to C1x (and empty at
> this point in time.)
Ah, thanks, I missed it on the first go-around.
But it would be extremely helpful if para 6 was not empty;
even a slightly incorrect form would be far more useful than
a simple "TBD" phrase.
-drt
Ok. It does have the advantage of showing exactly what changed (as
opposed to, in some cases, showing only the new text and discarding
the old), but it's not a huge deal. In any case, the person doing the
work gets to choose the format.
> lawrenc...@siemens.com writes:
>> Keith Thompson <ks...@mib.org> wrote:
>>>
>>> FWIW, I've seen drafts of the Ada standard that use a strikeout
>>> markup for deleted text and underlining for new text.
>>
>> I've seen other documents use the same convention but it's hard to do
>> with troff and I think it makes the document hard to read and
>> emphasizes the wrong things.
>
> Ok. It does have the advantage of showing exactly what changed (as
> opposed to, in some cases, showing only the new text and discarding
> the old), but it's not a huge deal. In any case, the person doing the
> work gets to choose the format.
Maybe there should be an ISO standard for the typography of ISO standard
documents.
Unfortunately not. There's a concern that publishing the source would
make it too easy for an unscrupulous person to create forged copies that
differ from the actual standard.
--
Larry Jones
I like Mom to be impressed when I fulfill the least of my obligations.
-- Calvin
There is, but only for the final standards, not for the drafts. :-)
(That's not strictly true, it's actually Part 2 of the ISO Directives
rather than a genuine ISO standard.)
--
Larry Jones
Another casualty of applied metaphysics. -- Hobbes
As Jacob has accurately pointed out, there *aren't* any major changes
yet. That's why they're still TBD.
--
Larry Jones
Who, ME? Who?! Me?? WHO... Me?! Who, me??? -- Calvin
But such forgeries would be easy to detect if the original troff
source is available (especially if it's accompanied by a PGP
signature).
Not if you print them out and sell them in dark alleys and street corners.
--
Andrew Poelstra apoe...@wpsoftware.com
To email me, use the above email addresss with .com set to .net
Good point. Next time I buy a copy of the C standard in a dark alley,
I'll just have to assume it's forged.
8-)}
How would having the original troff source (even with a PGP signature)
help the average person determine that their PDF or paper copy is a
forgery?
--
Larry Jones
OK, there IS a middle ground, but it's for sissy weasels. -- Calvin
Hmm.
Well, the PDF copies could be made available with a PGP signature as
well, or at least with SHA1 checksums published on the committee's web
site.
Paper copy? People still use paper? 8-)}
Yes, paper copies would be hard to verify (though you could still
easily detect alterations if you know or suspect what's been changed).
But the existence of published PDF copies makes paper copies easy
enough to forge anyway. It's not trivial, but someone who's strongly
motiviated (by what, exactly?) could make use of existing open source
software that can read and write the PDF format.
I don't think it's practical to make forgeries impossible, or even
particularly difficult. The solution, IMHO, is to make verified
(i.e., cryptographically signed) soft copies (PDF, troff, whatever)
easier to obtain than any hypothetical forgeries.
At least for drafts, this is already pretty much the case. Almost
everyone reading this knows where to download n1256.pdf. Some
unscrupulous person who tried to distribute a modified n1256.pdf would
be quickly discovered, and since PDF readers typically are able to
save as text (though perhaps not particularly legible text), we could
probably nail down just what was changed.
It is probably not very difficult for unscupulous yet motivated individuals
to create forged copies from the pdf file either. As a matter of fact, such
copies might not even be illegal since there is no copyright notice in
n1336.pdf at all.
OTOH, for us afficionados interested in the design and evolution of the C
language (pun intended), it is *much* simpler to keep track of changes
between textual documents with traditional editing tools. Even just
scanning the current 556 page draft with differences from n1256.pdf
highlighted is a pain. As further modifications will be included in later
drafts, this approach will become unworkable, because the newer differences
will become indistinguishable from "older" ones.
If the source form for the C Standard is a textual troff file, we would all
love to use it for reference and to keep track of differences. The reason
most of us did not ask for it sooner is we assumed it was in Microsoft Word
format, for which we have no particular inclination, and for which tools do
a lousy job at tackling.
--
Chqrlie.
>As a matter of fact, such copies might not even be illegal since
>there is no copyright notice in n1336.pdf at all.
A notice is not necessary to establish copyright.
--
dhs spe...@panix.com
As David Spencer points out, the document is implicitly copyrighted
even without a notice. I think an explicit notice still has some
legal meaning, but I won't try to elaborate.
But it's unlikely that would deter someone unscrupulous enough to want
to create a forgery in the first place. A forger would almost
certainly reproduce any copyright notice anyway.
This whole problem becomes a non-issue when everyone simply gets their
draft copies from WG14's official website. Of course, a checksum would
be a nice addition to have.
Yes, particularly courts of law and those who deal with them. We
techies tend to think of the standard as a technical document (which it
is), but it's primary commercial purpose is as a legal document. I
agree with most everything you said, but I don't make the rules, and
neither does the committee; it's the big wigs at ISO that have to be
convinced. I'm not even allowed to release the troff source to other
committee members (other than my backup editors), let alone the general
public.
--
Larry Jones
Fortunately, that was our plan from the start. -- Calvin
I'm pretty confident that future drafts will have diff marks against the
previous draft, so only new changes will be marked.
--
Larry Jones
What's the matter? Don't you trust your own kid?! -- Calvin
I hesitate to tell the guy doing the work how to do it, but I don't
hesitate for long. 8-)}
Would it be possible to have, for example, single change bars showing
changes from the previous draft and double change bars showing changes
either from C99 or from n1256? Then we wouldn't have to go through
*all* the drafts to figure out what's changed.
Your concern is touching. :-)
> Would it be possible to have, for example, single change bars showing
> changes from the previous draft and double change bars showing changes
> either from C99 or from n1256?
Anything is possible, but no, that really isn't practical.
--
Larry Jones
Moms and reason are like oil and water. -- Calvin
I notice in the Foreword on page xi (pdf page 11):
4 Attention is drawn to the possibility that some of the elements
of this document may be the subject of patent rights. ISO and IEC
shall not be held responsible for identifying any or all such
patent rights.
It is fairly general consensus that standards must (MUST) under no
circumstances depend on something proprietary such as patents.
Due to the MS-OOXML debacle ISO has severely damaged its reputation. It
will have to work very hard to regain it. Leaving implementors or users
of the C standard potentially at risk of being sued is not the right way
to do that.
--
___ Olaf 'Rhialto' Seibert -- You author it, and I'll reader it.
\X/ rhialto/at/xs4all.nl -- Cetero censeo "authored" delendum esse.
Without such an understanding a Standard would be unable to use any
mechanism for which a patent existed even though the patent holder was
happy for it to be used. IMHO that would be ridiculous.
Okay, there may be some slight difference in how strongly worded such
consensus is (and different parties would differ in opinion which
formulation is the stronger one[1]). The end result is similar: as a
user or implementor of the standard, one need not worry about sudden
patent lawsuits.
In any case, I strongly suspect that the paragraph in the Draft is there
due to pressure from the higher levels of ISO, not because the committee
likes it so much. And unfortunately, the higher levels of ISO seem more
and more to be involved in the corruption[2].
[1] an owner of a patent that is potentially to be included into some
standard might like your wording less than mine.
[2] http://www.groklaw.net/articlebasic.php?story=20080815140101554 ,
http://www.groklaw.net/articlebasic.php?story=20080718170044877 etc
In the spirit of principle 13, I'm throwing this up here in hopes of
livening support for the proposed stdatomic.h interface. This implementation
is GCC specific, though it should be trivial to port to MSC, etc, in a
lock-free manner, implementing only compare_swap with compiler intrinsics.
Everything is static. I aborted my attempt to be able to switch extern and
static declarations because I'm lazy, and it caused headaches with
libraries, anyhow (when libraries also used the types). GCC can remove the
dead code for the time being.
Requires GCC 4.1+, and you must specify -march for GCC to emit proper code.
I use this for mundane object juggling chores between threads, as well as
for a Win32 sigaction implementation.
Please feel free to send comments and patches my way. I make no guarantees
about correctness and async-safety, of course ;)
/* ==========================================================================
* stdatomic.h - Portable implementation of C++0x N2324 stdatomic.h proposal.
* --------------------------------------------------------------------------
* Copyright (c) 2008 William Ahern
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
* ==========================================================================
* SYNOPSIS
*
* Portable stdatomic.h implementation, as described in "C++ Atomic Types and
* Operations":
*
* http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2324.html
*
* ATOMIC_SCALAR_LOCK_FREE enum { 0, 1, 2 }
*
* memory_order enum { memory_order_relaxed,
* memory_order_acquire,
* memory_order_release,
* memory_order_acq_rel,
* memory_order_seq_cst }
*
* atomic_flag Binary flag. Always lock-free.
* atomic_bool Boolean.
* atomic_address Void pointer.
* atomic_char, atomic_uchar, atomic_short, atomic_ushort, atomic_int,
* atomic_uint, atomic_long, atomic_ulong, atomic_llong, atomic_ullong
*
* /--------------+------+------+---------+----------\
* | | flag | bool | address | integral |
* +--------------+------+------+---------+----------+
* | test_and_set | O | . | . | . |
* | clear | O | . | . | . |
* | store | . | O | O | O |
* | load | . | O | O | O |
* | swap | . | O | O | O |
* | compare_swap | . | O | O | O |
* | fence | . | O | O | O |
* | fetch_add | . | . | O | O |
* | fetch_sub | . | . | O | O |
* | fetch_and | . | . | . | O |
* | fetch_or | . | . | . | O |
* | fetch_xor | . | . | . | O |
* +--------------+------+------+---------+----------+
* | lock_free | . | O | O | O |
* \--------------+------+------+---------+----------/
*
* ==========================================================================
*/
#ifndef C1X_STDATOMIC_H
#define C1X_STDATOMIC_H
#include <stdbool.h> /* bool */
#include <limits.h> /* LLONG_MAX */
#ifndef ATOMIC_SCOPE
#define ATOMIC_SCOPE static
#endif
typedef enum memory_order {
memory_order_relaxed, memory_order_acquire, memory_order_release,
memory_order_acq_rel, memory_order_seq_cst
} memory_order;
typedef struct atomic_flag atomic_flag;
typedef struct atomic_bool atomic_bool;
typedef struct atomic_address atomic_address;
typedef struct atomic_char atomic_char;
typedef struct atomic_schar atomic_schar;
typedef struct atomic_uchar atomic_uchar;
typedef struct atomic_short atomic_short;
typedef struct atomic_ushort atomic_ushort;
typedef struct atomic_int atomic_int;
typedef struct atomic_uint atomic_uint;
typedef struct atomic_long atomic_long;
typedef struct atomic_ulong atomic_ulong;
#if defined(LLONG_MAX)
typedef struct atomic_llong atomic_llong;
typedef struct atomic_ullong atomic_ullong;
#endif
ATOMIC_SCOPE const struct atomic__flag_ops {
bool (*test_and_set)(atomic_flag *, memory_order);
void (*clear)(atomic_flag *, memory_order);
} atomic__flag_ops_initializer;
ATOMIC_SCOPE const struct atomic__bool_ops {
bool (*lock_free)(atomic_bool *);
void (*store)(atomic_bool *, bool, memory_order);
bool (*load)(atomic_bool *, memory_order);
bool (*swap)(atomic_bool *, bool, memory_order);
bool (*compare_swap)(atomic_bool *, bool *, bool, memory_order);
void (*fence)(atomic_bool *, memory_order);
} atomic__bool_ops_initializer;
ATOMIC_SCOPE const struct atomic__address_ops {
bool (*lock_free)(atomic_address *);
void (*store)(atomic_address *, void *, memory_order);
void *(*load)(atomic_address *, memory_order);
void *(*swap)(atomic_address *, void *, memory_order);
bool (*compare_swap)(atomic_address *, void **, void *, memory_order);
void (*fence)(atomic_address *, memory_order);
void *(*fetch_add)(atomic_address *, void *, memory_order);
void *(*fetch_sub)(atomic_address *, void *, memory_order);
} atomic__address_ops_initializer;
#define ATOMIC__DECL_INTEGRAL_OPS(type, name) \
ATOMIC_SCOPE const struct atomic__##name##_ops { \
bool (*lock_free)(atomic_##name *); \
void (*store)(atomic_##name *, type, memory_order); \
type (*load)(atomic_##name *, memory_order); \
type (*swap)(atomic_##name *, type, memory_order); \
bool (*compare_swap) \
(atomic_##name *, type *, type, memory_order); \
void (*fence)(atomic_##name *, memory_order); \
type (*fetch_add)(atomic_##name *, type, memory_order); \
type (*fetch_sub)(atomic_##name *, type, memory_order); \
type (*fetch_and)(atomic_##name *, type, memory_order); \
type (*fetch_or)(atomic_##name *, type, memory_order); \
type (*fetch_xor)(atomic_##name *, type, memory_order); \
} atomic__##name##_ops_initializer
ATOMIC__DECL_INTEGRAL_OPS(char, char);
ATOMIC__DECL_INTEGRAL_OPS(signed char, schar);
ATOMIC__DECL_INTEGRAL_OPS(unsigned char, uchar);
ATOMIC__DECL_INTEGRAL_OPS(short, short);
ATOMIC__DECL_INTEGRAL_OPS(unsigned short, ushort);
ATOMIC__DECL_INTEGRAL_OPS(int, int);
ATOMIC__DECL_INTEGRAL_OPS(unsigned int, uint);
ATOMIC__DECL_INTEGRAL_OPS(long, long);
ATOMIC__DECL_INTEGRAL_OPS(unsigned long, ulong);
#if defined(LLONG_MAX)
ATOMIC__DECL_INTEGRAL_OPS(long long, llong);
ATOMIC__DECL_INTEGRAL_OPS(unsigned long long, ullong);
#endif
#define atomic_test_and_set(a) ((a)->ops->test_and_set((a), memory_order_seq_cst))
#define atomic_clear(a) ((a)->ops->clear((a), memory_order_seq_cst))
#define atomic_lock_free(a) ((a)->ops->lock_free((a)))
#define atomic_load(a) ((a)->ops->load((a), memory_order_seq_cst))
#define atomic_store(a, n) ((a)->ops->store((a), (n), memory_order_seq_cst))
#define atomic_swap(a, n) ((a)->ops->swap((a), (n), memory_order_seq_cst))
#define atomic_compare_swap(a, m, n) ((a)->ops->compare_swap((a), (m), (n), memory_order_seq_cst))
#define atomic_fence(a, o) ((a)->ops->fence((a), (o)))
#define atomic_fetch_add(a, n) ((a)->ops->fetch_add((a), (n), memory_order_seq_cst))
#define atomic_fetch_sub(a, n) ((a)->ops->fetch_sub((a), (n), memory_order_seq_cst))
#define atomic_fetch_and(a, n) ((a)->ops->fetch_and((a), (n), memory_order_seq_cst))
#define atomic_fetch_or(a, n) ((a)->ops->fetch_or((a), (n), memory_order_seq_cst))
#define atomic_fetch_xor(a, n) ((a)->ops->fetch_xor((a), (n), memory_order_seq_cst))
/*
* XXX: Eventually these type definitions might need to be target specific.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#define ATOMIC_FLAG_INIT { 0, &atomic__flag_ops_initializer }
struct atomic_flag {
volatile int i;
const struct atomic__flags_ops *ops;
}; /* struct atomic_flag */
#define ATOMIC_BOOL_INIT { 0, &atomic__bool_ops_initializer }
struct atomic_bool {
volatile bool i;
const struct atomic__bool_ops *ops;
}; /* struct atomic_bool */
#define ATOMIC_ADDRESS_INIT { 0, &atomic__address_ops_initializer }
struct atomic_address {
volatile void *i;
const struct atomic__address_ops *ops;
}; /* struct atomic_address */
#define ATOMIC__DECL_INTEGRAL(type, name) \
struct atomic_##name { \
volatile type i; \
const struct atomic__##name##_ops *ops; \
} /* struct atomic_integral */
#define ATOMIC_CHAR_INIT { 0, &atomic__char_ops_initializer }
ATOMIC__DECL_INTEGRAL(char, char);
#define ATOMIC_SCHAR_INIT { 0, &atomic__schar_ops_initializer }
ATOMIC__DECL_INTEGRAL(signed char, schar);
#define ATOMIC_UCHAR_INIT { 0, &atomic__uchar_ops_initializer }
ATOMIC__DECL_INTEGRAL(unsigned char, uchar);
#define ATOMIC_SHORT_INIT { 0, &atomic__short_ops_initializer }
ATOMIC__DECL_INTEGRAL(short, short);
#define ATOMIC_USHORT_INIT { 0, &atomic__ushort_ops_initializer }
ATOMIC__DECL_INTEGRAL(unsigned short, ushort);
#define ATOMIC_INT_INIT { 0, &atomic__int_ops_initializer }
ATOMIC__DECL_INTEGRAL(int, int);
#define ATOMIC_UINT_INIT { 0, &atomic__uint_ops_initializer }
ATOMIC__DECL_INTEGRAL(unsigned int, uint);
#define ATOMIC_LONG_INIT { 0, &atomic__long_ops_initializer }
ATOMIC__DECL_INTEGRAL(long, long);
#define ATOMIC_ULONG_INIT { 0, &atomic__ulong_ops_initializer }
ATOMIC__DECL_INTEGRAL(unsigned long, ulong);
#if defined(LLONG_MAX)
#define ATOMIC_LLONG_INIT { 0, &atomic__llong_ops_initializer }
ATOMIC__DECL_INTEGRAL(long long, llong);
#define ATOMIC_ULLONG_INIT { 0, &atomic__ullong_ops_initializer }
ATOMIC__DECL_INTEGRAL(unsigned long long, ullong);
#endif
#ifdef __GNUC__
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)
#error "Must use GCC 4.1.x or greater"
#endif
/* 0 = Never, 1 = Sometimes, 2 = Always */
#define ATOMIC_SCALAR_LOCK_FREE 2
typedef union {
atomic_flag *flag_; atomic_bool *bool_; atomic_address *address_;
atomic_char *char_; atomic_schar *schar_; atomic_uchar *uchar_;
atomic_short *short_; atomic_ushort *ushort_;
atomic_int *int_; atomic_uint *uint_;
atomic_long *long_; atomic_ulong *ulong_;
#if defined(LLONG_MAX)
atomic_llong *llong_; atomic_ullong *ullong_;
#endif
} atomic__any __attribute__ ((__transparent_union__));
static bool atomic__any_lock_free(atomic__any p) {
return 1;
} /* atomic__any_lock_free() */
static bool atomic__flag_test_and_set(atomic_flag *p, memory_order o) {
if (o >= memory_order_acq_rel)
__sync_synchronize();
return !!__sync_lock_test_and_set(&p->i, 1);
} /* atomic__flag_test_and_set() */
static void atomic__flag_clear(atomic_flag *p, memory_order o) {
__sync_lock_release(&p->i);
if (o >= memory_order_acq_rel)
__sync_synchronize();
} /* atomic__flag_clear() */
ATOMIC_SCOPE const struct atomic__flag_ops atomic__flag_ops_initializer =
{ &atomic__flag_test_and_set, &atomic__flag_clear };
static void atomic__bool_store(atomic_bool *p, bool n, memory_order o) {
bool j = atomic_load(p);
while (!atomic_compare_swap(p, &j, n))
;
} /* atomic__bool_store() */
static bool atomic__bool_load(atomic_bool *p, memory_order o) {
return (bool)__sync_fetch_and_or(&p->i, 0U);
} /* atomic__bool_load() */
static bool atomic__bool_swap(atomic_bool *p, bool n, memory_order o) {
bool j = atomic_load(p);
while (!atomic_compare_swap(p, &j, n))
;;
return j;
} /* atomic__bool_swap() */
static bool atomic__bool_compare_swap(atomic_bool *p, bool *m, bool n, memory_order o) {
bool j = *m;
*m = (bool)__sync_val_compare_and_swap(&p->i, j, n);
return j == *m;
} /* atomic__bool_compare_swap() */
static void atomic__bool_fence(atomic_bool *p, memory_order o) {
return /* void */;
} /* atomic__bool_fence() */
ATOMIC_SCOPE const struct atomic__bool_ops atomic__bool_ops_initializer =
{ &atomic__any_lock_free, &atomic__bool_store, &atomic__bool_load,
&atomic__bool_swap, &atomic__bool_compare_swap, &atomic__bool_fence };
#define ATOMIC__GCC_IMPL_STORE(type, name) \
static void atomic__##name##_store \
(atomic_##name *p, type n, memory_order o) { \
type j = atomic_load(p); \
\
while (!atomic_compare_swap(p, &j, n)) \
;; \
} /* atomic__store() */
#define ATOMIC__GCC_IMPL_LOAD(type, name) \
static type atomic__##name##_load(atomic_##name *p, memory_order o) { \
return (type)__sync_fetch_and_or(&p->i, 0U); \
} /* atomic__load() */
#define ATOMIC__GCC_IMPL_SWAP(type, name) \
static type atomic__##name##_swap \
(atomic_##name *p, type n, memory_order o) { \
type j = atomic_load(p); \
\
while (!atomic_compare_swap(p, &j, n)) \
;; \
\
return j; \
} /* atomic__swap() */
#define ATOMIC__GCC_IMPL_COMPARE_SWAP(type, name) \
static bool atomic__##name##_compare_swap \
(atomic_##name *p, type *m, type n, memory_order o) { \
type j = *m; \
\
*m = (type)__sync_val_compare_and_swap(&p->i, j, n); \
\
return j == *m; \
} /* atomic__compare_swap() */
#define ATOMIC__GCC_IMPL_FENCE(type, name) \
static void atomic__##name##_fence(atomic_##name *p, memory_order o) { \
return /* void */; \
} /* atomic__fence() */
#define ATOMIC__GCC_IMPL_FETCH_ADD(type, name) \
static type atomic__##name##_fetch_add \
(atomic_##name *p, type n, memory_order o) { \
return (type)__sync_fetch_and_add(&p->i, n); \
} /* atomic__fetch_add() */
#define ATOMIC__GCC_IMPL_FETCH_SUB(type, name) \
static type atomic__##name##_fetch_sub \
(atomic_##name *p, type n, memory_order o) { \
return (type)__sync_fetch_and_sub(&p->i, n); \
} /* atomic__fetch_sub() */
#define ATOMIC__GCC_IMPL_FETCH_AND(type, name) \
static type atomic__##name##_fetch_and \
(atomic_##name *p, type n, memory_order o) { \
return (type)__sync_fetch_and_and(&p->i, n); \
} /* atomic__fetch_and() */
#define ATOMIC__GCC_IMPL_FETCH_OR(type, name) \
static type atomic__##name##_fetch_or \
(atomic_##name *p, type n, memory_order o) { \
return (type)__sync_fetch_and_or(&p->i, n); \
} /* atomic__fetch_or() */
#define ATOMIC__GCC_IMPL_FETCH_XOR(type, name) \
static type atomic__##name##_fetch_xor \
(atomic_##name *p, type n, memory_order o) { \
return (type)__sync_fetch_and_xor(&p->i, n); \
} /* atomic__fetch_xor() */
#define ATOMIC__GCC_IMPL_METHODS(type, name) \
ATOMIC__GCC_IMPL_STORE(type, name) \
ATOMIC__GCC_IMPL_LOAD(type, name) \
ATOMIC__GCC_IMPL_SWAP(type, name) \
ATOMIC__GCC_IMPL_COMPARE_SWAP(type, name) \
ATOMIC__GCC_IMPL_FENCE(type, name)
#define ATOMIC__GCC_IMPL_FETCH_METHODS(type, name) \
ATOMIC__GCC_IMPL_FETCH_ADD(type, name) \
ATOMIC__GCC_IMPL_FETCH_SUB(type, name) \
ATOMIC__GCC_IMPL_FETCH_AND(type, name) \
ATOMIC__GCC_IMPL_FETCH_OR(type, name) \
ATOMIC__GCC_IMPL_FETCH_XOR(type, name)
ATOMIC__GCC_IMPL_METHODS(void *, address)
ATOMIC__GCC_IMPL_FETCH_ADD(void *, address)
ATOMIC__GCC_IMPL_FETCH_SUB(void *, address)
ATOMIC_SCOPE const struct atomic__address_ops atomic__address_ops_initializer =
{ &atomic__any_lock_free, &atomic__address_store, &atomic__address_load,
&atomic__address_swap, &atomic__address_compare_swap, &atomic__address_fence,
&atomic__address_fetch_add, &atomic__address_fetch_sub };
#define ATOMIC__GCC_IMPL_INTEGRAL(type, name) \
ATOMIC__GCC_IMPL_METHODS(type, name) \
ATOMIC__GCC_IMPL_FETCH_METHODS(type, name) \
ATOMIC_SCOPE const struct atomic__##name##_ops \
atomic__##name##_ops_initializer = \
{ &atomic__any_lock_free, \
&atomic__##name##_store, &atomic__##name##_load, \
&atomic__##name##_swap, &atomic__##name##_compare_swap, \
&atomic__##name##_fence, &atomic__##name##_fetch_add, \
&atomic__##name##_fetch_sub, &atomic__##name##_fetch_and, \
&atomic__##name##_fetch_or, &atomic__##name##_fetch_xor };
ATOMIC__GCC_IMPL_INTEGRAL(char, char)
ATOMIC__GCC_IMPL_INTEGRAL(signed char, schar)
ATOMIC__GCC_IMPL_INTEGRAL(unsigned char, uchar)
ATOMIC__GCC_IMPL_INTEGRAL(short, short)
ATOMIC__GCC_IMPL_INTEGRAL(unsigned short, ushort)
ATOMIC__GCC_IMPL_INTEGRAL(int, int)
ATOMIC__GCC_IMPL_INTEGRAL(unsigned int, uint)
ATOMIC__GCC_IMPL_INTEGRAL(long, long)
ATOMIC__GCC_IMPL_INTEGRAL(unsigned long, ulong)
#if defined(LLONG_MAX)
ATOMIC__GCC_IMPL_INTEGRAL(long long, llong)
ATOMIC__GCC_IMPL_INTEGRAL(unsigned long long, ullong)
#endif
#endif /* __GNUC__ */
#endif /* C1X_STDATOMIC_H */
#if 0
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
atomic_ulong a = ATOMIC_ULONG_INIT;
unsigned long i = atoi(argv[1]);
i = atomic_swap(&a, i);
printf("%lu => %lu\n", i, atomic_load(&a));
i = atomic_fetch_add(&a, 3);
printf("%lu => %lu\n", i, atomic_load(&a));
return 0;
} /* main() */
#endif
Indeed, that specific paragraph is required (by ISO/IEC) for standards
where no patent rights have been identified during its preparation. If
patent rights are identified, then different text identifying them is
required.
--
Larry Jones
Geez, I gotta have a REASON for everything? -- Calvin
> Rhialto <rhi...@falu.nl> wrote:
> >
> > In any case, I strongly suspect that the paragraph in the Draft is there
> > due to pressure from the higher levels of ISO, not because the committee
> > likes it so much.
>
> Indeed, that specific paragraph is required (by ISO/IEC) for standards
> where no patent rights have been identified during its preparation.
IMO, this should be made explicit. If not, you're just worrying people
for no good reason. (And no, I don't consider "covering ISO's upper
brass's arses" to be good reason; not if it, in effect, uncovers all
innocent users' arses.)
Richard
>Well, the PDF copies could be made available with a PGP signature as
>well, or at least with SHA1 checksums published on the committee's web
>site.
problematic, since the committee copy couldn't account for cover matter
other than ISO's. so a special tool would be needed too.
worse, some are now watermarked during delivery (to identify the
purchaser).
It is so sad to see that the C language does not deserve a better
standardizing body that makes its electronic documents available for free to
all, such as ECMA.
--
Chqrlie
How do you propose the ISO should be funded, then?
DES
--
Dag-Erling Smørgrav - d...@des.no
Perhaps the same way ECMA is funded?
In practice, though, I find my free copy of n1256.pdf more useful than
the copy of the ISO C99 standard that I paid for.
Did the money I paid (to ANSI) for my copy of the C99 standard
actually go to support the work that was done to create it? I thought
the committee members had to pay for themselves.
ECMA is a much smaller organization with a much smaller scope and
portfolio...
And it is funded by industry.
--
dik t. winter, cwi, science park 123, 1098 xg amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Keith Thompson wrote:
> Dag-Erling Smørgrav <d...@des.no> writes:
> > "Charlie Gordon" <ne...@chqrlie.org> writes:
> >> It is so sad to see that the C language does not deserve a better
> >> standardizing body that makes its electronic documents available for
> >> free to all, such as ECMA.
> >
> > How do you propose the ISO should be funded, then?
>
> Perhaps the same way ECMA is funded?
>
> In practice, though, I find my free copy of n1256.pdf more useful than
> the copy of the ISO C99 standard that I paid for.
>
> Did the money I paid (to ANSI) for my copy of the C99 standard
> actually go to support the work that was done to create it? I thought
> the committee members had to pay for themselves.
Committee members pay their own expenses to meetings.
SCC22/WG14 members have used that to leverage the general
availability of draft copies of the C standards N1256 and
currently N1401 on www.
There are still many reasons to support the various standards
organizations that distribute the C standards. The standards
organizations like ISO represented by ANSI in the US do
the administrative work setting standards for the standards
and administer the process where draft documents are
submitted to member countries for approval.
The approval process is far from a foregone conclusion and
serves to make the committee members consider many points of
view not represented by the attending members and countries.
ISO/ANSI are industrial standards organizations supported by
those who benefit from standards agreed upon by interested
parties. It is reasonable that the industry that benefits should pay
for those benefits.
Currently they are both freely available and paid for by interested
parties
Regards,
Walter..
--
Walter Banks
Byte Craft Limited
Tel. (519) 888-6911
http://www.bytecraft.com
wal...@bytecraft.com
I gather that the amount that they pay is insufficient to support the
full costs associated with the standardization process. I would imagine
that those costs might include administrative support, arranging the
meetings, a share of the costs associated with the ISO web site from
which you can order the documents, etc., though I can't be sure of the
details. Those costs are relatively small, but then so is the total
amount of revenue to be collected from the committee members membership
fees. The number of copies of the finished document that actually get
sold is also pretty small, so it might be the case that ISO barely make
any net profit, possibly none at all, on the sale of these documents.
However, I've never seen any official numbers proving whether or not
they actually do make a net profit, so I can't be sure of any of this.