A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3493.htm below:

Array subscripting without decay

when the item is inside a

*/ } ul /* Whole unordered list */ { } ul li /* Unordered list item */ { } ol /* Whole ordered list */ { } ol li /* Ordered list item */ { } hr {} /* ---- Some span elements --- */ sub /* Subscripts. Pandoc: H~2~O */ { } sup /* Superscripts. Pandoc: The 2^nd^ try. */ { } em /* Emphasis. Markdown: *emphasis* or _emphasis_ */ { } em > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > p > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > * > p > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > p > ins > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > * > p > ins > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } /* ---- Links (anchors) ---- */ a /* All links */ { /* Keep links clean. On screen, they are colored; in print, they do nothing anyway. */ text-decoration: none; } @media screen { a:hover { /* On hover, we indicate a bit more that it is a link. */ text-decoration: underline; } } @media print { a { /* In print, a colored link is useless, so un-style it. */ color: black; background: transparent; } a[href^="http://"]:after, a[href^="https://"]:after { /* However, links that go somewhere else, might be useful to the reader, so for http and https links, print the URL after what was the link text in parens */ content: " (" attr(href) ") "; font-size: 90%; } } /* ---- Images ---- */ img { /* Let it be inline left/right where it wants to be, but verticality make it in the middle to look nicer, but opinions differ, and if in a multi-line paragraph, it might not be so great. */ vertical-align: middle; } div.figure /* Pandoc figure-style image */ { /* Center the image and caption */ margin-left: auto; margin-right: auto; text-align: center; font-style: italic; } p.caption /* Pandoc figure-style caption within div.figure */ { /* Inherits div.figure props by default */ } /* ---- Code blocks and spans ---- */ pre, code { background-color: #fdf7ee; /* BEGIN word wrap */ /* Need all the following to word wrap instead of scroll box */ /* This will override the overflow:auto if present */ white-space: pre-wrap; /* css-3 */ white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */ white-space: -pre-wrap; /* Opera 4-6 */ white-space: -o-pre-wrap; /* Opera 7 */ word-wrap: break-word; /* Internet Explorer 5.5+ */ /* END word wrap */ } pre /* Code blocks */ { /* Distinguish pre blocks from other text by more than the font with a background tint. */ padding: 0.5em; /* Since we have a background color */ border-radius: 5px; /* Softens it */ /* Give it a some definition */ border: 1px solid #aaa; /* Set it off left and right, seems to look a bit nicer when we have a background */ margin-left: 0.5em; margin-right: 0.5em; } pre.yacc, code.yacc { background-color: #f0f0f0; } pre.yacc /* Code blocks */ { /* Distinguish pre blocks from other text by more than the font with a background tint. */ padding: 0.0em; /* Since we have a background color */ border-radius: 5px; /* Softens it */ /* Give it a some definition */ border: 0px solid #aaa; /* Set it off left and right, seems to look a bit nicer when we have a background */ margin-left: 0.0em; margin-right: 0.0em; } @media screen { pre { white-space: pre; /* Dotted looks better on screen and solid seems to print better. */ border: 1px dotted #777; } } code /* All inline code spans */ { } p > code, li > code /* Code spans in paragraphs and tight lists */ { /* Pad a little from adjacent text */ padding-left: 2px; padding-right: 2px; } li > p code /* Code span in a loose list */ { /* We have room for some more background color above and below */ padding: 2px; } span.option { color: blue; text-decoration: underline; } /* ---- Math ---- */ span.math /* Pandoc inline math default and --jsmath inline math */ { /* Tried font-style:italic here, and it messed up MathJax rendering in some browsers. Maybe don't mess with at all. */ } div.math /* Pandoc --jsmath display math */ { } span.LaTeX /* Pandoc --latexmathml math */ { } eq /* Pandoc --gladtex math */ { } /* ---- Tables ---- */ /* A clean textbook-like style with horizontal lines above and below and under the header. Rows highlight on hover to help scanning the table on screen. */ table { border-collapse: collapse; border-spacing: 0; /* IE 6 */ border-bottom: 2pt solid #000; border-top: 2pt solid #000; /* The caption on top will not have a bottom-border */ /* Center */ margin-left: auto; margin-right: auto; } thead /* Entire table header */ { border-bottom: 1pt solid #000; background-color: #eee; /* Does this BG print well? */ } tr.header /* Each header row */ { } tbody /* Entire table body */ { } /* Table body rows */ tr { } tr.odd:hover, tr.even:hover /* Use .odd and .even classes to avoid styling rows in other tables */ { background-color: #eee; } /* Odd and even rows */ tr.odd {} tr.even {} td, th /* Table cells and table header cells */ { vertical-align: top; /* Word */ vertical-align: baseline; /* Others */ padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.2em; padding-bottom: 0.2em; } /* Removes padding on left and right of table for a tight look. Good if thead has no background color*/ /* tr td:last-child, tr th:last-child { padding-right: 0; } tr td:first-child, tr th:first-child { padding-left: 0; } */ th /* Table header cells */ { font-weight: bold; } tfoot /* Table footer (what appears here if caption is on top?) */ { } caption /* This is for a table caption tag, not the p.caption Pandoc uses in a div.figure */ { caption-side: top; border: none; font-size: 0.9em; font-style: italic; text-align: center; margin-bottom: 0.3em; /* Good for when on top */ padding-bottom: 0.2em; } /* ---- Definition lists ---- */ dl /* The whole list */ { border-top: 2pt solid black; padding-top: 0.5em; border-bottom: 2pt solid black; } dt /* Definition term */ { font-weight: bold; } dd+dt /* 2nd or greater term in the list */ { border-top: 1pt solid black; padding-top: 0.5em; } dd /* A definition */ { margin-bottom: 0.5em; } dd+dd /* 2nd or greater definition of a term */ { border-top: 1px solid black; /* To separate multiple definitions */ } /* ---- Footnotes ---- */ a.footnote, a.footnoteRef { /* Pandoc, MultiMarkdown footnote links */ font-size: small; vertical-align: text-top; } a[href^="#fnref"], a.reversefootnote /* Pandoc, MultiMarkdown, ?? footnote back links */ { } @media print { a[href^="#fnref"], a.reversefootnote /* Pandoc, MultiMarkdown */ { /* Don't display these at all in print since the arrow is only something to click on */ display: none; } } div.footnotes /* Pandoc footnotes div at end of the document */ { } div.footnotes li[id^="fn"] /* A footnote item within that div */ { } table tr td,th { border-right: 1px solid; border-left: 1px solid; } /* You can class stuff as "noprint" to not print. Useful since you can't set this media conditional inside an HTML element's style attribute (I think), and you don't want to make another stylesheet that imports this one and adds a class just to do this. */ @media print { .noprint { display:none; } }

target

integration into IS ISO/IEC 9899:202y

document history n3493 202408 Original proposal n3335 202409 Fixes to the constratint based on the length of the array. Added the informal proposal for discarded code. Intrduced the terms top level fixed/variable length array. n3352 202409 Adds the [] operator to compound literals. Tweeks the wording of the unary & operator. Modifies the condition on when the index can equal the length of the array. n3360 202409 Adds the [] operator to named constants. Puts the upper bound on the lenght of the array on named and compound literal constants. n3380 202410 Do not remove index[array], yet, but deprecate it. Do not deal with named constants, yet. n3493 202502 Reformulate the rules for array decay and prefer the term operand over expression Polls by WG14, Oct 2024, Minneapolis Does WG14 want something along the lines of N3360 into C2y? 12 2 5 direction Does WG14 object to breaking index[array] as in N3360? 8 5 6 no consensus Does WG14 want to deprecate index[array] as in N3360 in C2y? 10 1 8 direction Does WG14 want to make a constraint violation out of negative integer constant expressions used as subscripts of an array (not a pointer) as in n3360 in C2y? 14 1 5 direction license

CC BY, see https://creativecommons.org/licenses/by/4.0

Discussion

Traditionally, the definition of array subscripting goes through conversion of the array to a pointer. Thus, E[m] is defined as (*((E)+(m))), where E is converted to a pointer to its first element. On first sight it may seem there is no semantic difference between this and saying that “E[m] denotes the mth element of the array”. But indeed there is; the paragraph on conversion of an array to a pointer says

Except when […], an expression that has type “array of type” is converted to an expression with type “pointer to type” that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

Therefore, subscripting an array precludes its declaration with register. This seems an artificial restriction, existing only because of the way E[m] is defined. Implementations such as gcc have lifted this restriction since decades.

It was also noted that the expression *(E+m) produces an lvalue in instances where a non-lvalue would be expected for E[m], as in

struct {const int i; int arr[1];} func();
func().i;           // not lvalue
func.arr[0];        // equivalent to the following
*(func().arr+0);    // non-const, immutable lvalue with temporary lifetime

This paper changes this, and so the provision of the standard that introduces temporary object for values with an array member, will only trigger in the rare case that the array member is used in places where a pointer value is expected. With the proposed changes we have

struct {const int i; int arr[1];} func();
func().i;           // not lvalue, no temporary object instantiated
func.arr[0];        // not lvalue, no temporary object instantiated
*(func().arr+0);    // non-const, immutable lvalue with temporary lifetime

A similar restriction is present for the use as integer constant expressions (ICE). Consider

constexpr int x[3]= {0,10,20};
float y[x[1]];

This code is not valid because x[1] is not an integer constant expression. Since the whole object x is a constant expression, it seems each of its members should be usable as ICE. Previous versions of this paper tried to change this, but now we delay this to a follow-up paper.

Other problems arose when studying the extension of the subscripting operation to allow range selections.

Constraint on the subscript

In an expression E[M], where E is an array, we propose M to be ≥ 0 and for it to be a constraint if M is an integer constant expression. This is not imposed if E has pointer type, neither as constraint nor as UB. In particular, for a pointer p the common idiom p[-1] remains valid. If E is an array this was already invalid, since, from the definitions of arrays in C, the element E[-1] does not exist, even if E were to decay to a pointer. Thus:

int A[3][3];
A[1][-1];  // A[1] is an array of three elements; say, B. B[-1] does not exist.
           // In *(B-1), the pointer B (once B decays to a pointer) points to the
           // the first element of an array of 3 elements. B-1 is not a valid pointer.
           // Hence, *(A[1]-1), hence A[1][-1], has UB as per the current standard.

An implementation may very well define this behavior and allow it. More likely, an implementation may just compute the adress A[1]-1 and have this code work without defining the behavior (it just works). Programmers relying on that can rewrite A[1][-1] (which henceforth will raise a diagnostic) to *(A[1]-1) in order to avoid the diagnostic.

Nevertheless it is unclear to us if that UB is not used by optimizers to make assumptions about subscripts, so using this UB on arrays is inherently dangerous. Therefore we propose to promote this from UB to a constraint in situations that are easily detectable at translation time, namely when the subscript is an ICE.

Drawback

The following code is valid today and would require a diagnostic if the constraint is introduced also for an out-of-bounds access beyond the array length:

#define SAFE_ACCESS(a, x) (((x) < ARRAY_SIZE(a)) ? a[x] : 0)
int a[10];
int b = SAFE_ACCESS(a, 10);

This macro is superseded by the constraint, but is still useful for VLA. A user of this macro would have to replace all uses for fixed length arrays by a direct access or change the macro so that the subscript is not an ICE even if x is.

Here the out-of-bound index is valid because the expression is not evaluated. However, writing “if the expression is evaluated” in the constraint is not adequate because being evaluated is a runtime property. There are contexts where the expression is known not to be evaluated already at translation time. It is for these contexts than an execption can be made in the constraint. However, this concept is not developed in the standard, and its introduction falls outside the scope of this proposal.

Wording

New text is underlined green, removed text is stroke-out red. Possible reorganization of the paragraphs is left to the discretion of the editors.

Array-to-pointer decay

6.3.2.1 Lvalues, arrays, and function designators

3 Except when it is the operand of the sizeof operator, or typeof operators, or the unary & operator, or is a string literal used to initialize an array, an expression that has type “array of type” is converted to an expression with type “pointer to type” that points to the initial element of the array object and is not an lvalue. An expression that has type “array of type” is converted to an expression with type “pointer to type” that points to the initial element of the array object except when it is an operand of the sizeof operator, the typeof operators, the unary & operator, the array subscripting operator, or if it is a string literal used to initialize an array. The resulting pointer is not an lvalue. If the array object has register storage class, the behavior is implementation-defined.

Postfix operators

6.5.3 Postfix operators

6.5.3.2 Array subscripting

Description

1 A postfix expression followed by an expression in square brackets [ ] is a subscripted designation of an element of an array. The use of this operator with the first operand of integer type is an obsolescent feature.

Constraints

2 One of the expressions operands shall have type “pointer to complete object type” or “array of type”, the other expression operand , called the subscript, shall have integer type, and the result has type “type”. If one of the two operands has array type and the subscript is an integer constant expression, the value of the latter shall not be negative.

Semantics

3 A postfix expression followed by an expression in square brackets [ ] is a subscripted designation of an element of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))). Because of the conversion rules that apply to the binary + operator, if E1 is an array object (equivalently, a pointer to the initial element of an array object) and E2 is an integer, E1[E2] designates the E2-th element of E1 (counting from zero). If either operand has pointer type the expression E1[E2] is equivalent to *((E1)+(E2)) and is an lvalue. Otherwise, let E be the operand of array type and let m be the value of the subscript; the array subscript expression designates the m-th element of the array designated by E, counting from zero. It is an lvalue if E is an lvalue. m shall not be negative and shall be less than the length of the array or equal to it; it shall only equal the length of the array if the [] operator is followed by zero or more [] operators with subscripts equal to zero and the resulting postfix expression is the operand of the unary & operator or is converted to an expression with pointer type as described in 6.3.2.1.

4 Successive subscript operators designate an element of a multidimensional array object. If E is an n-dimensional array (n ≥ 2) with dimensions i × j × ⋯ × k, then E[N] (used as other than an lvalue) is converted to a pointer to denotes an (n − 1)-dimensional array with dimensions j × ⋯ × k. If the unary * operator is applied to this pointer explicitly, or implicitly as a result of subscripting, the result is the referenced (n − 1)-dimensional array, which itself is converted into a pointer if used as other than an lvalue. It follows from this that arrays are stored in row-major order (last subscript varies fastest).

5 EXAMPLE The following snippet has an array object defined by the declaration:

Here x is a 3 × 5 array of objects of type int; more precisely, x is an array of three element objects, each of which is an array of five objects of type int. In the expression x[i], which is equivalent to (*((x)+(i))), x is first converted to a pointer to the initial array of five objects of type int. Then i is adjusted according to the type of x, which conceptually entails multiplying i by the size of the object to which the pointer points, namely an array of five int objects. The results are added and indirection is applied to yield an array of five objects of type int. When used in the expression x[i][j], that array is in turn converted to a pointer to the first of the objects of type int, so x[i][j] yields an int. The expression x[1] designates the second element of array x, which is itself an array of five objects of type int. Then x[1][2] designates the third element thereof, which is an int. It is the 7-th stored element of the two-dimensional array x (counting from 0).

6.5.4 Unary operators

6.5.4.3 Address and indirection operators

3 …, neither the & operator nor the unary * nor the access to the value that is implied by the [] is evaluated …

Storage class register

6.7.2 Storage-class specifiers

Remove the last sentence in the following footnote

127) The implementation can treat any register declaration simply as an auto declaration. However, whether or not addressable storage is used, the address of any part of an object declared with storage-class specifier register cannot be computed, either explicitly (by use of the unary & operator as discussed in 6.5.4.3) or implicitly (by converting an array name to a pointer as discussed in 6.3.3.1). Thus, the only operator that can be applied to an array declared with storage-class specifier register is sizeof and the typeof operators.

Future language directions

6.11 Future language directions

6.11.4a Postfix operators

The use of the array subscripting operator with an operand of integer type followed by an operand of pointer or array type enclosed in square brackets is an obsolescent feature.
Acknowledgment

We’d like to thank Martin Uecker, Joseph Myers and Robert Seacord for their suggestions.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4