ISO/ IEC JTC1/SC22/WG14 N892

	Document Number: N892	
	Date: 13-Sept-1999
	-Issue #1-
Author: Clive Feather <clive@demon.net>
Date: 1999年06月27日
Subject: default argument conversion of float _Complex
Summary
-------
For consistency with real floating types, the type float _Complex should be
promoted by the default argument promotions to double _Complex.
Suggested Technical Corrigendum
-------------------------------
Change 6.5.2.2p6 in part, from:
 and arguments that have type float are promoted to double.
to:
 and arguments that have a corresponding real type of float are
 promoted, without change of type domain, to a type whose corresponding
 real type is double.

	- Issue #2-
Author: Clive Feather <clive@demon.net>
Date: 1999年06月27日
Subject: handling of imaginary types
Summary
-------
The handling of imaginary types in the Standard is somewhat inconsistent. For
example, they are not mentioned at all in 6.2.5 (other than a footnote), but
are treated as first-class types in 6.7.2. Annex G makes certain assumptions
about such types but these assumptions are not supported by the Standard.
Details
-------
There are two reasonable approaches that could be followed. The first is to
remove all mention of imaginary types from the main text of the Standard
and put them all in Annex G. The second is to make the basic properties of
imaginary types part of the main language (while still making them
optional), leaving Annex G to handle the details of ISO 60559 imaginary
types.
After some thought, the author of this DR feels that imaginary types are
experimental enough that the first approach is better and has worded the
Suggested Technical Corrigendum on that basis.
The keyword _Imaginary is mentioned in 6.4.1, 6.7.2, and 7.3.1. These
references - and any related text - are all to be removed and replacement
wording added to Annex G.
A new subclause G.4.4 is added. This specifies the practical implications
of giving imaginary types the same representation and alignment as real
floating types.
Suggested Technical Corrigendum
-------------------------------
Delete "_Imaginary" from the list of keywords in 6.4.1. If this is felt to
be too radical, instead add the following text to paragraph 2:
 The keyword _Imaginary is not used in the C language, but is reserved
 for specifying imaginary types such as described in Annex G.
Delete "_Imaginary" from 6.7.2p1 and the three imaginary cases from 6.7.2p2.
Change 6.7.2p3 to read:
 The type specifier _Complex shall not be used if the implementation
 does not provide complex types.
Delete 7.3.1p3. Delete "imaginary" from 7.3.1p5. Replace 7.3.1p4 with:
 The macro
 I
 expands to _Complex_I.
Add a new paragraph before G.2p1:
 There is a new keyword _Imaginary used to specify imaginary types.
 It is used as a type-specifier within declaration-specifiers in the
 same way as _Complex is (thus "_Imaginary float" is a valid type name).
Add a new subclause G.4.4
 G.4.4 Interchangable values
 Though imaginary types are not compatible with the corresponding real
 type, values of one may be used where the other is expected in the
 following cases. In each case the value is converted to the value of the
 other type that has the same representation (that is, by multiplying by
 the imaginary unit when converting to an imaginary type, and by dividing
 by the imaginary unit when converting to a real type).
 - one type is the type of the parameter, and the other type the
 type of the argument, when a function is called without a prototype
 in scope; [*]
 - one type is the type of an argument corresponding to a trailing
 ellipsis in a function call and the other is specified as the
 type argument of an invocation of the va_arg macro;
 - one type is the type of an argument to a function such as fprintf
 or the type pointed to by an argument to a function such as fscanf,
 and the other is the type implied by the corresponding conversion
 specifier.
 [*] If a prototype is in scope, conversion is as if by assignment and
 the value will be converted to zero.
Replace G.6p1 with:
 The macros
 imaginary
 and
 _Imaginary_I
 are defined, respectively, as _Imaginary and a constant expression of
 type const float _Imaginary with the value of the imaginary unit.
 The macro
 I
 is defined to be _Imaginary_I (not _Complex_I as stated in 7.3).
 Notwithstanding the provisions of 7.1.3, a program may undefine and
 then perhaps redefine the macro imaginary.
Afternote
---------
If WG14 wishes to take the alternative approach of moving _Imaginary types
more firmly into the body of the Standard, then the following areas would
be affected.
- Do not make any of the above changes.
- Add text to 4p6 explaining that imaginary types are never required.
- Merge the text from G.2 into 6.2.5.
- Merge the existing text from G.4 into 6.3.1.
- Make the cases described in the new G.4.4 above further cases of the
 relevant subclauses (6.5.2.2, 7.15.1.1, 7.19.6.1, 7.19.6.2, 7.24.2.1,
 and 7.24.2.2).
- Move G.5.1p1 and G.5.2p1 into 6.5.5 and 6.5.6.
- Delete G.6p1.

	-Issue #3-
Author: Clive Feather <clive@demon.net>
Date: 1999年09月06日
Subject: ambiguity in initialization
Summary
-------
When there is more than one initializer for the same object it is not
clear whether both initializers are actually evaluated. Wording changes
are proposed to clarify this.
Details
-------
Subclause 6.7.8 paragraph 19 reads:
 The initialization shall occur in initializer list
 order, each initializer provided for a particular subobject
 overriding any previously listed initializer for the same
 subobject; all subobjects that are not initialized
 explicitly shall be initialized implicitly the same as
 objects that have static storage duration.
Paragraph 23 reads:
 The order in which any side effects occur among the
 initialization list expressions is unspecified.
If the same object is initialized twice, as in:
 int a [2] = { f (0), f (1), [0] = f (2) };
the term "overriding" could be taken to mean that the first initializer is
ignored completely, or it could be taken to mean that the expression is
evaluated and then discarded. The proposed wording change assumes the
latter.
Suggested Technical Corrigendum
-------------------------------
Replace 6.7.8 paragraph 23 with:
 All the initialization list expressions are evaluated, even if the
 resulting value will be overridden, but the order in which any side
 effects occur is unspecified.

	- Issue #4-
Author: Clive Feather <clive@demon.net>
Date: 1999年09月11日
Subject: binding of multibyte conversion state objects
Summary
-------
There is a general belief that multibyte conversion state objects (or at
least those associated with streams) are bound to a given locale when first
used. However, the Standard does not support this belief and in fact
contradicts it. The author believes that common practice matches the belief
and not the Standard, and therefore submits that the latter should be
changed.
Discussion
----------
Consider the following function to convert a file from one encoding to
another. The macro CONVERT is assumed to convert a wide character between
the two encodings - it is expected that this will often be a no-op. Error
checking has been omitted for clarity.
 void conv_file (char *fn1, char *fn2, char *loc1, char *loc2)
 {
 setlocale (LC_CTYPE, loc1);
 FILE *f1 = fopen (fn1, "r");
 wchar_t c = fgetwc (f1);
 setlocale (LC_CTYPE, loc2);
 FILE *f2 = fopen (fn2, "w");
 while (c != WEOF)
 {
 fputwc (CONVERT (c), f2);
 c = fgetwc (f1);
 }
 }
Most people would be surprised to discover that this code does not work
unless two extra setlocale calls are added to the inner loop:
 {
 setlocale (LC_CTYPE, loc2);
 fputwc (CONVERT (c), f2);
 setlocale (LC_CTYPE, loc1);
 c = fgetwc (f1);
 }
Similarly, consider a function to convert a block from one multibyte
encoding to another:
 void conv_data (char *p1, char *p2, char *loc1, char *loc2)
 {
 char *p1e = strchr (p1, '0円') + 1;
 setlocale (LC_CTYPE, loc1);
 mbstate_t mb1 = { 0 };
 wchar_t c;
 p1 += mbrtowc (&c, p1, p1e - p1, &mb1);
 setlocale (LC_CTYPE, loc2);
 mbstate_t mb2 = { 0 };
 p2 += wcrtomb (p2, CONVERT (c), &mb2);
 while (c != 0)
 {
 p1 += mbrtowc (&c, p1, p1e - p1, &mb1);
 p2 += wcrtomb (p2, CONVERT (c), &mb2);
 }
 }
Again this actually requires two setlocale calls in the inner loop.
Clause 7.24.6p3 reads, in part:
 If an mbstate_t object has been altered by any of the functions
 described in this subclause, and is then used with a different
 multibyte character sequence, or in the other conversion direction,
 or with a different LC_CTYPE category setting than on earlier
 function calls,the behavior is undefined.
Put another way, each mbstate_t object is initially "unbound" (if it is
initialized to zero) and then becomes "bound" by any call to a function
such as mbrtowc or wcrtomb. When "bound" it can only be used in the
same direction with the same string as originally bound, and only when the
LC_CTYPE category is that in effect when it was bound.
With ordinary mbstate_t objects this is a annoyance; one implication is
that a new object must be created every single time a new string is to be
converted (the Standard does not provide any way to "unbind" the object).
With the mbstate_t object inside a FILE structure it is even worse, because
it makes it impossible to (for example) write to a file, rewind it, and
then read the same file. Similarly, the internal mbstate_t objects used
when the mbstate_t pointer argument is set to NULL can be used for only
one string in the entire program !
Users of mbstate_t objects (including those in FILE structures) expect them
to continue to work even when the locale is changed, and expect to be able
to use them for more than a single purpose.
Potential solutions
-------------------
Any change to the Standard needs to not affect existing code. Luckily this
is fairly simple: existing code must only use the mbstate_t object in the
locale it was bound to and in the same way as when it was initially bound.
However, any change should also make the above code work.
One naive proposal is that, whenever a mbstate_t object returns to the
initial state, it becomes unbound and can then be rebound. However, in most
locales the initial state occurs often, and therefore there is a major risk
that the object will be bound to the wrong locale at that time.
The actual proposal below works in three stages:
(1) Once an mbstate_t object is bound to a locale, it remains bound to
that locale even after a call to setlocale(). [This gives meaning to code
that is currently undefined, but does not affect any existing correct code.]
(2) Explicit mechanisms are provided to change the status of an mbstate_t
object in several ways:
- return to the initial state, making it available for future conversion
 in either direction [for the wide->multi direction this was already
 possible using wcrtomb, while for the multi->wide direction a minor change
 is made to mbrtowc utilising previously unspecified behaviour];
- unbind the object, returning it to the initial state [done by assigning
 a zero value to it or with the new __mbsbind function];
- bind to a new locale, returning the mbstate_t object to the initial state
 [done with the new __mbsbind function].
(3) Various changes are made to the way that the mbstate_t object hidden
in a FILE is processed. The previous changes ensure that, once bound to a
locale, it remains bound to it. It can be returned explicitly to the
initial state by a call to fseek, and also returns to the initial state
after input reaches end-of-file (these choices were made to correspond
with the requirements of 7.19.5.3p6 for changing I/O direction). Finally
a new __mbsfbind function is provided to unbind the object or bind it to
the current locale.
(4) The internal mbstate_t objects associated with the mbrlen, mbrtowc,
wcrtomb, mbsrtowcs, and wcsrtombs functions can only be used with the
locale they initially bind to. Semantics are proposed to force the object
to the unbound state; these use previously impossible cases where they
exist, or in the case of wcrtomb are upwards compatible.
Efficiency
----------
Some concerns have been expressed that, on some implementations, changing
locale is a "heavyweight" operation and that such changes should therefore
be resisted. However, the proposed changes do not actually alter the
situation: the same locales will still be used at the same time. What does
become possible is for the mbstate_t to usefully contain a pointer to
cached locale information, and for the cache to be maintained more
effectively.
Suggested Technical Corrigendum
-------------------------------
(Changes concerning explicit mbstate_t objects.)
Change 7.24.6p3 to:
 [#3] The initial conversion state corresponds, for a
 conversion in either direction, to the beginning of a new
 multibyte character in the initial shift state. An mbstate_t
 object may be "unbound" or "bound". A zero-valued mbstate_t
 object is (at least) one way to describe an unbound object,
 and if an mbstate_t object is assigned such a value it it
 becomes unbound. All unbound mbstate_t objects are in the
 initial conversion state. An unbound object can be used to
 initiate conversion involving any multibyte character
 sequence, in any LC_CTYPE category setting, and then becomes
 bound to that category setting. When a bound mbstate_t
 object is used with any of the functions described in this
 subclause, the category it is bound to is used irrespective
 of the current LC_CTYPE category setting. If an mbstate_t
 object has been altered by any of the functions described in
 this subclause so as to not be in the initial conversion
 state, and is then used with a different multibyte character
 sequence, or in the other conversion direction, than on the
 most recent such function call, the behavior is undefined.290)
Append to footnote 290:
 Furthermore, provided that the object is in the initial
 conversion state, it can then be used in converting a new
 string or in the other direction.
 
Add a new subclause 7.24.6.2.2:
 7.24.6.2.2 The __mbsbind function
 Synopsis
 [#1]
 #include <wchar.h>
 int __mbsbind(mbstate_t *ps, int loc);
 Description
 [#2] The value of loc shall be 0 or 1. If ps is not a null
 pointer, the pointed-to mbstate_t object is made unbound
 (if loc is 0) or bound to the current LC_CTYPE category
 setting in the initial conversions state (if loc is 1),
 irrespective of its previous state.
 Returns
 [#3] The __mbsbind function returns zero normally or a
 negative value if ps is a null pointer or some other error
 occurred.290a)
 290a The __mbsbind function is not required to detect any
 other errors.
Change 7.24.6.3p1 and 7.24.6.4p1 from:
 [...] which is initialized at program startup to the initial
 conversion state. [...]
to:
 [...] which is initialized at program startup to the unbound
 state. [...]
Change 7.24.6.3.2p2 to:
 [#2] If s is a null pointer, the mbrtowc function is
 equivalent to the call:
 mbrtowc(NULL, "", 1, ps)
++ except that the resulting state described is the initial
++ conversion state even if an encoding error occurred.290b)
 In this case, the values of the parameters pwc and n are
 ignored.
++ 290b The only possible return values are 0 and (size_t)-1.
++ The effect is reliably to set *ps to the initial conversion
++ state while remaining bound.
In 7.24.6.3.2p4, change "positive" to "<= n" (the two error values are
actually large and positive).
Append a footnote to 7.24.6.3.3p2:
 291a The effect is reliably to set *ps to the initial
 conversion state while remaining bound.
(Changes concerning mbstate_t objects associated with streams.)
Append to 7.19.2p6:
 If a wide character input function encounters end-of-file, or
 after a successful call to the fseek function, the mbstate_t
 object associated with the stream describes the initial
 conversion state.
Append to the last sentence of 7.19.9.2p5:
 and if the stream is wide-oriented the associated mbstate_t
 object shall be set to the initial conversion state.
In 7.24.3.1p2, change:
to:
 [...] If the stream
 is at end-of-file, the end-of-file indicator for the stream
++ is set, the mbstate_t object associated with the stream is
++ set to the initial conversions state,
 and fgetwc returns WEOF. [...]
Add a new subclause 7.24.6.2.3:
 7.24.6.2.3 The __mbsfbind function
 Synopsis
 [#1]
 #include <stdio.h>
 #include <wchar.h>
 int __mbsfbind(FILE *stream, int loc);
 Description
 [#2] The __mbsfbind function is equivalent to:
 if (fwide(stream, 1)> 0)
 __mbsbind(&mbsobj, loc);
 where mbsobj is the mbstate_t object associated with stream
 when it is wide-oriented, except that the returned value
 can represent different errors.
 Returns
 [#3] The __mbsfbind function returns zero normally or a
 negative value if some error occurred.290c)
 290c The __mbsfbind function is not required to detect any
 errors.
(Changes associated with internal mbstate_t objects.)
Append to 7.24.6.3.2p3:
 As a special case, if n is (size_t)-1 then ps becomes unbound
 irrespective of its previous state and an unspecified value
 is returned.
Append to 7.24.6.3.3p2:
 If additionally ps is a null pointer, the internal mbstate_t
 object becomes unbound irrespective of its previous state.
Append to 7.24.6.4p2:
 As a special case, if src is a null pointer then the normal
 behaviour of the function is ignored and instead ps becomes
 unbound irrespective of its previous state; an unspecified
 value is returned.

AltStyle によって変換されたページ (->オリジナル) /