9

The C23 standard apparently has introduced using "auto" keyword for auto type deduction, see here, just like in C++11. However, there seems to be some differences.

According to here, https://en.cppreference.com/w/cpp/keyword/auto, after C++11, auto is no longer a storage duration specifier in C++.

However, I cannot easily find an equivalently statement for C23. Is it the case that auto is still a storage class specifier in C in C23?

Can we still write int auto x = 1; in C23?

EDIT: The answer to the first question is yes. But as pointed out by Andrew Henle in comments below, the second question is different:

Can we still write float auto x = 1; in C23?

As quoted by @AndrewHenle and @VladfromMoscow, in the standard document, 6.7.1 Storage-class specifiers, paragraph 4

auto shall only appear in the declaration specifiers of an identifier with file scope or along with other storage class specifiers if the type is to be inferred from an initializer.

It seems that this does not cover the case float auto x = 1;, if this declaration is not in file scope.

What's the interpretation of this?

There is another question: the sentence seems confusing because we surely can use auto without "other storage specifiers", couldn't we? Like auto a = 1;.

Mr User
  • 205
  • 1
  • 5
  • 3
    Where do you see such a statement on the page that you linked with "see here"? I don't even find any occurrence of "auto" there. – JayK May 14 '23 at 18:11
  • From my reading [of the latest *draft* C23 standard that I'm aware of](https://open-std.org/JTC1/SC22/WG14/www/docs/n3096.pdf), **6.7.1 Storage-class specifiers**, paragraph 1 and **6.7.9 Type inference**, it seems to me C23 is attempting to retain the legacy use of `auto` while adding something close to the C++11 and later use of `auto` for type inference, likely as an attempt to not break legacy code. But I'll defer to those more astute in reading the C standard than I am (and it's also a *draft*...) – Andrew Henle May 14 '23 at 18:18
  • 1
    @JayK It's [**6.7.9 Type inference**](https://open-std.org/JTC1/SC22/WG14/www/docs/n3096.pdf) in the latest *draft* of C23 that I'm aware of. AFAICT, the question seems correct despite the sourcing. – Andrew Henle May 14 '23 at 18:24
  • 1
    "_It seems that this does not cover the case float auto x = 1;_": No type is to be inferred in this case. – user17732522 May 14 '23 at 19:50
  • 1
    @user17732522 That's why the case is not covered, hence we have the question. – Mr User May 14 '23 at 20:35
  • @MrUser There is nothing to be covered (at function scope). No rule forbids `auto` in this declaration (in particular not the one you quote, since no type is inferred) and it has no effect (as in previously in C). – user17732522 May 14 '23 at 21:05
  • To be fair, it was @VladfromMoscow who first quoted the draft C23 standard. – Andrew Henle May 14 '23 at 21:06
  • @user17732522 *No rule forbids `auto` in this declaration* This seems to: "`auto` shall only appear in the declaration specifiers of an identifier ... if the type is to be inferred from an initializer." If the type is **not** to be inferred from an initializer, that can be read as "`auto` shall **not** appear...", which sure sounds like it could be read as a prohibition to me. The standard here is as clear as mud. :-/ – Andrew Henle May 14 '23 at 21:08
  • @AndrewHenle One more thing - `auto` can certainly be used *without* other storage class specifiers, because that's how we use `auto x = 1;`. It is confusing. – Mr User May 14 '23 at 21:40
  • To me the sentence structure intuitively reads as `X shall only do Y if Z` with `or` as part of `Y`. And that structure to me intuitively seems to formalize to `(X does Y) implies Z`, rather than `Z implies (X does Y)` or even `Z is equivalent to (X does Y)`. But I don't know whether linguistically there is any support for that. However my reading would make sense in keeping old usage as well as the new form valid while making e.g. `auto static int x = 0;` invalid as it should be. – user17732522 May 14 '23 at 21:43
  • 1
    @user17732522 The rationale and intent for `auto` can be found here: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3007.htm – Andrew Henle May 14 '23 at 21:44

3 Answers3

6

Yes, auto is still a storage-class specifier in C23:

See 6.7.1 Storage-class specifiers:

  • auto
  • constexpr
  • extern
  • register
  • static
  • thread_local
  • typedef
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • I'm not totally convinced this answers the question, "can we still write `int auto x = 1;` in C23?" What about the limitations that **6.7.1 Storage-class specifiers**, paragraph 4 places on the use of `auto`: "`auto` shall only appear in the declaration specifiers of an identifier with file scope or along with other storage class specifiers if the type is to be inferred from an initializer." And with respect to that, it's unclear what exactly the phrase "if the type is to be inferred from an initializer" applies to. – Andrew Henle May 14 '23 at 18:32
  • @AndrewHenle _"if the type is to be inferred from an initializer"_ is the new thing making it possible to infer the type from the initializer used. I don't see that that part has an effect on the old usage so `int auto x = 1;` or `auto int x = 1;` is still fine. – Ted Lyngmo May 14 '23 at 18:35
  • 6.7.1p4 shortened reads "`auto` shall only appear ... if the type is to be inferred from an initializer." `int auto x = 1;` would seem to violate that as the type is not being inferred. `double auto d = 1;` is even more troubling. At least `1` is an `int`. – Andrew Henle May 14 '23 at 18:38
  • @AndrewHenle There's an `or` in the paragraph though. `double auto d = 1;` makes `d` a `double` with automatic storage duration. `auto d = 1;` would make `d` an `int` and it's only in the second example the type is inferred. – Ted Lyngmo May 14 '23 at 18:46
  • @TedLyngmo The expression `double auto d = 1;` does NOT infer the type. Thus is does NOT satisfy the condition "if the type is to be inferred from an initializer", as pointed out by Andrew Henle. Does that make `double auto d = 1;` something not in line with the standard? – Mr User May 14 '23 at 19:13
  • @MrUser I said that it's only in `auto d = 1;` that the type will be inferred and that `double auto d = 1;` makes `d` a `double` (just like in previous versions). – Ted Lyngmo May 14 '23 at 20:04
  • So, the first part of the qoute, the part before "or" applies. – Ted Lyngmo May 14 '23 at 20:17
  • @TedLyngmo The part before "or" says "file scope". But what about local variables? – Mr User May 14 '23 at 20:34
  • @MrUser Since it says _"declaration specifiers of an identifier with file scope"_ that seems to disqualify local variables. – Ted Lyngmo May 14 '23 at 21:13
  • @TedLyngmo *There's an or in the paragraph though.* I'd think if it were supposed to read "X or (Y and Z)" it would have been written more as "X, or Y and Z" with a comma or something to separate the two. But it's written as "X or Y and Z", which can be read as "(X or Y) and Z". At best, it's ambiguous wording. – Andrew Henle May 14 '23 at 21:13
  • @AndrewHenle I only see X and Y :-) _"`auto` shall only appear in the declaration specifiers of an identifier with file scope"_ is the X and _"or along with other storage class specifiers if the type is to be inferred from an initializer"_ is the Y. – Ted Lyngmo May 14 '23 at 21:16
  • @TedLyngmo In my XYZ example, I'm using "X" as "identifier with file scope", "Y" as "along with other storage class specifiers", and "Z" as "if the type is to be inferred from an initializer". I could say the operator precedence for that has not been specified. – Andrew Henle May 14 '23 at 21:27
3

In C23 auto is still a storage class specifier.

From the C 23 (6.7.1 Storage-class specifiers)

Syntax

1 storage-class-specifier:
    auto
    constexpr
    extern
    register
    static
    thread_local
    typedef

and

Semantics

6 Storage-class specifiers specify various properties of identifiers and declared features:

— storage duration (static in block scope, thread_local, auto, register),

4 thread_local shall not appear in the declaration specifiers of a function declaration. auto shall only appear in the declaration specifiers of an identifier with file scope or along with other storage class specifiers if the type is to be inferred from an initializer

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
2

float auto x = 1; is valid and means the same thing as in pre-C23 (and auto here is as redundant as in pre-C23). There is no indication in the working draft that it might not be the case.

auto shall only appear in the declaration specifiers of an identifier with file scope or along with other storage class specifiers if the type is to be inferred from an initializer.

This does not cover float auto x = 1; at a function scope. In this declaration, auto still specifies storage duration because:

Storage-class specifiers specify various properties of identifiers and declared features:

  • storage duration (static in block scope, thread_local, auto, register),

and this meaning of auto is not ignored because

If auto appears with another storage-class specifier, or if it appears in a declaration at file scope, it is ignored for the purposes of determining a storage duration or linkage

and auto does not specify that the type shall be inferred because

For a declaration such that the declaration specifiers contain no type specifier a mechanism to infer the type from an initializer is discussed in 6.7.9

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243