C23 auto vs C++11 auto
Asked Answered
F

3

12

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;.

Fyrd answered 14/5, 2023 at 17:33 Comment(11)
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.Hackler
From my reading of the latest draft C23 standard that I'm aware of, 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...)Zachar
@Hackler It's 6.7.9 Type inference in the latest draft of C23 that I'm aware of. AFAICT, the question seems correct despite the sourcing.Zachar
"It seems that this does not cover the case float auto x = 1;": No type is to be inferred in this case.Bilberry
@Bilberry That's why the case is not covered, hence we have the question.Fyrd
@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).Bilberry
To be fair, it was @VladfromMoscow who first quoted the draft C23 standard.Zachar
@Bilberry 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. :-/Zachar
@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.Fyrd
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.Bilberry
@Bilberry The rationale and intent for auto can be found here: open-std.org/jtc1/sc22/wg14/www/docs/n3007.htmZachar
P
7

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
Personally answered 14/5, 2023 at 18:14 Comment(12)
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.Zachar
@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.Personally
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.Zachar
@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.Personally
@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?Fyrd
@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).Personally
So, the first part of the qoute, the part before "or" applies.Personally
@TedLyngmo The part before "or" says "file scope". But what about local variables?Fyrd
@MrUser Since it says "declaration specifiers of an identifier with file scope" that seems to disqualify local variables.Personally
@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.Zachar
@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.Personally
@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.Zachar
S
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

Sallee answered 14/5, 2023 at 18:18 Comment(4)
See my edited question. Do you think that int auto a = 1 is allowed?Fyrd
@MrUser In C23 there is written that "A declaration for which the type is inferred shall contain the storage-class specifier auto." So it seems such a declaration int auto x = 1; is invalid in C23.Sallee
So in that aspect C23 is quite similar to C++?Fyrd
@MrUser Yes, they become more close to each other taking also in account the new keyword in C constexprSallee
P
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

Procurable answered 14/5, 2023 at 21:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.