4 ms·
Looking at the primer... // C typedef struct { int a; struct { double x; } bar; } Foo; // C3 struct F
by addaon 4y ago
Looking at the primer...
// C
typedef struct
{
int a;
struct
{
double x;
} bar;
} Foo;
// C3
struct Foo
{
int a;
struct bar
{
double x;
}
}
Very confused by this. The C code declares an anonymous struct type, then aliases the typename "Foo" to that anonymous struct type. The C3 code seems to declares a named struct type "Foo" -- why isn't the C equivalent here just "struct Foo"?
But then within the struct it gets weirder... the C code declares a second anonymous struct, and then declares a member variable of that type. The C3 code... declares a struct named "bar" and also a member variable with name matching the type? Except the primer says that these are equivalent, so the C3 code is declaring an anonymous struct and a member of that type? Using the same syntax as the outer declaration did to declare a named type but no (global) variable?? Is this case sensitive?
I don't think I can get further into the primer than this... even taking the author at their word that the two snippets are equivalent, I don't understand what's in play (case sensitivity? declarations where variable name must match type name?) to make this sane, and there's zero rationale given for these decisions.
- addaon 4y agoOh gosh... digging further on the same page under "Identifiers" it looks like case sensitivity is the key here. So "struct Foo" declares a type "Foo", and "struct foo" declares a variable "foo" of new anonymous type. I assume "struct Foo foo" and "struct bar Bar" do exactly what you (don't) expect, and maybe even "struct foo bar baz {}" to be the equivalent of the C code "struct {} foo, bar, baz"... yikes. Edit: "Declaring more than one variable at a time is not allowed." So there's no equivalent to the C code ""struct {} foo, bar, baz"... not clear if "struct IDontNeedANameButTheLanguageIsForcingMe foo {}; IDontNeedANameButTheLanguageIsForcingMe bar; IDontNeedANameButTheLanguageIsForcingMe baz;" is legal (modulo that some of those semicolons are illegal I think?). Yeah, this needs some rigor in the docs.
- Cloudef 4y agoThis doesn't seem very well thought out at all
- deleted 4y ago[deleted]
- lerno 4y agoNo, you misunderstand. There is no `struct Foo foo`. Unlike C `struct Foo` would only ever be valid at the top level. Neither `struct Foo foo` nor `struct bar Bar` works. The reason why `Bar` is a type and `bar` is a variable or function is to resolve the ambiguity of C syntax without having to rely on unlimited lookahead or the lexer hack. Basically it allows tools to parse the code much more easily than they would C. You can declare multiple fields in a struct, e.g. `struct Foo { int x, y; }`, but you can't write `int x, y = 123;` like in C. This is because it would create ambiguities in the extended for/while/if syntax C3 adds.
- lerno 4y agoThe first part about the name is just like C++: you use the name without `struct` unlike C where structs has its own namespace. That's what it's meant to illustrate. The second question is more subtle. In C, the syntax is `struct { ... } [optional member name] ;`. Because there is no anonymous struct at the top level, the anonymous structs inside of a struct has a different syntax, also eschewing the final `;`, changing the syntax to `struct [optional member name] { ... }`. If the C syntax structure is desired a final `;` would be required. This syntax change comes from C2.
- addaon 4y agoBut what if I want to name the inner struct so I can refer to Outer::Inner (for example, for use with sizeof or similar, or to create a temporary to hold a copy of that type) later? Do I need to use typeof(Outer::inner)? And then of course multiple members of the same type...
- lerno 4y agoYou can't name the inner struct. So here are the options: Say that you want this from C: struct Foo { struct Bar { int x; int y; } bar; }; struct Foo f; f.bar = (struct Bar) { .x = 123 }; The struct in C3: struct Foo { struct bar { int x; int y; } }; Foo f; It is correct that we don't get the inner type, but because C3 has inference for {} assignment can happen despite that: f.bar = { .x = 123 }; // Valid in C3 You can grab the type using typeof if you want, but interestingly there's also the possibility to use structural casts, which are valid in C3: struct HelperStruct { int x; int y; } HelperStruct test = (HelperStruct)f.bar; // structural cast But the normal way would be to create a named struct outside if you really need a named struct, e.g.: struct Bar { int x, y; } struct Foo { Bar bar; };
- mst 4y agoThat ... actually seems reasonable? If you need it to be first class visible outside, you declare it outside. I believe I could live with this.
- brabel 4y ago> why isn't the C equivalent here just "struct Foo"? That would not be the equivalent... you would then need to declare the type of Foo variables as: struct Foo myVar; With the typedef, and I assume with C3, you would do the more acceptable: Foo myVar;
- addaon 4y agoFrom the primer, C3 follows the C++ rules here, not C rules. Changing to using C++ struct/enum/union naming rules here is a much less invasive change than what I'm discussing.
- _gabe_ 4y ago> Very confused by this. The C code declares an anonymous struct type, then aliases the typename "Foo" to that anonymous struct type. The C3 code seems to declares a named struct type "Foo" -- why isn't the C equivalent here just "struct Foo"? I'm curious how familiar you are with C? In C++ you can do: struct Foo { // ... }; Foo myVar; But that's not how it works in C. In C this would be: struct Foo { // ... }; struct Foo myVar; Which is why many C developers typedef the struct so that they don't have to prefix struct types with the keyword. > I don't think I can get further into the primer than this... even taking the author at their word that the two snippets are equivalent Maybe don't judge the author on these things if you're not familiar with how C would work in this case? There's nothing wrong with not understanding a piece of code, but it's generally not a good idea to assume you have understanding of a language like C if you understand C++. People often conflate the two, but there are many quirks of C that C++ doesn't necessarily need to do and vice versa.
- Cloudef 4y agoI hate when c++ does this. I don't want automatic typedefs, keep the struct so I know what it is. Also causes annoying name conflicts ...
- boardwaalk 4y agoThe number of languages that have separate namespaces for the two things is very small. See all the C descendants that discarded that idea: C++, C#, Java, Rust, Go. You probably ought to just find a decent naming scheme to avoid those conflicts…
- Ontonator 4y agoI can’t speak for the others, but Rust definitely has separate namespaces for them. See https://doc.rust-lang.org/beta/reference/names/namespaces.html https://doc.rust-lang.org/beta/reference/names/namespaces.ht...
- Bytewave81 4y ago