C-standardization: ez vajon eszükbe jutott?

Nyilván nem, mert túl egyszerű és hasznos lenne.

Nevezetesen hogy a beágyazott struktúrák elemeit egyszerűsítve is el lehessen érni. Ez COBOL-ban még működött, de azóta fejlődtünk. (Bár mintha hallani véltem volna arról, hogy egyes fordítók egyéni bővítményként tudnak ilyet, ami persze egycsapásra nem old meg semmit, erre nem lehet építeni.)

typedef struct Inner {
    int i1;
    int i2;
} Inner;

typedef struct Outer {
    Inner inner;
    int o1;
    int o2;
} Outer;

int main (void) {
    Outer proba;

    proba.i1= 1;
    proba.i2= 2;
}

Ugyanez másnak is eszébe jutott: https://stackoverflow.com/questions/41325638/accessing-a-member-in-a-ne…

 

Szerk: nyilván az sem jutott eszükbe hogy

struct X1 extends X0 {
...
}

vagyis az X1 kezdete az X0 összes mezője azonos névvel és tipussal. (Illetve van egy tíz nagyságrenddel bonyolultabb termék, ami tud ilyet is, de most maradjunk a C-nyelvnél.)

Hozzászólások

Szerkesztve: 2020. 04. 04., szo – 10:38

Vegyes a kép, ugyanis vannak bonyolultabb helyzetek. A te megoldásodban ez hogyan lenne feloldva?
 

typedef struct Inner {
    int i1;
    int i2;
} Inner;

typedef struct Outer {
    Inner inner1;
    Inner inner2;
    int o1;
    int o2;
} Outer;

int main (void) {
    Outer proba;

    proba.inner1.i1= 1;
    proba.inner1.i2= 2;

    proba.inner2.i1= 11;
    proba.inner2.i2= 22;
}

Hátrány: ha csinálok egy inner-t, akkor húdejó, fordul. Majd ha egyik modulhoz kell egy inner2, akkor a teljes C projekt többi C fájljai is hibával elhasalnak, mert onnantól azok sem tudják már kitalálni. Azaz vezethető végig a teljes C projek összes állományán, míg szisztematikusság esetén ez a probléma nem áll fenn a bővítésnél.
Én további szigorírás irányának örülnék, akár egy a fájl elejére írható '#pragma strict_mode;' ha lenne és ez a "normál" C-hez képest még több szigort vezetne be, ezt szívesen használnálm.

Például egy elsőre vicces, de egy nagyobb projektben igen alattomos bugok forrása az alábbi, amikor egyik enum-ba beszúrsz egy újabb állapotot és a másik enum-ot tartalmazó összehasonlítás valami hülye félreszámolást okoz:

enum Aaa {Alma111, Alma333};
enum Bbb {Alma1, Alma3};

int main() {
    enum Aaa a = Alma3;   // Aaa::Alma3 hogyan???
    enum Bbb b = Alma111; // Bbb::Alma111 hogyan???
}

Ugyanis összehasonlításoknál, switch-case esetében szintén nem reklamál semmi, ha másik enum-ból származó cimkét használok fel.

Amióta a Rust nyelvet is alaposan megismertem, azóta kontrasztosan látom, mi mindent kellene egy 'strict_mode'-os C-nél megvalósítani. Rust esetén nem fog lefordulni a cimkék összekeverése:

enum Aaa {Alma111, Alma333}
enum Bbb {Alma1, Alma3}

fn main() {
    let a: Aaa = Aaa::Alma333; // Oké
    let b: Bbb = Bbb::Alma3;   // Oké

    let c: Aaa = Aaa::Alma3;   // ERROR: variant or associated item not found in `Aaa`
    let d: Aaa = Bbb::Alma3;   // ERROR: expected enum `Aaa`, found enum `Bbb`
}

És ha az Outer struktúrának ugyanúgy van i1 és i2 eleme? Akkor hogyan éred el az Inner struktúráét egyszerűsítetten, úgy, hogy ne legyen ütközés? Amennyiben oka van, hogy az a két elem benne van egy külön konténerben, akkor logikus, hogy a konténeren keresztül hivatkozik rá az ember.

Ezt azert igy nem kene. Ez megsem python vagy javascript vagy php. 

Nem igazán támogatnám az ötletet. Elsőre jópofának tűnik, de számos buktatója lehet, ahogy itt fentebb többen is leírták előttem.

Tapasztalataim szerint minden „könnyítés” megbosszulja magát a nyelven előbb-utóbb. Bármely nyelven... Én már annak se örülök hogy a C nyelv olyan végtelenül kedves és időnként csak úgy magától castolgat nekem dolgokat, mondván hogy ekkor meg akkor lehet, mert nincs adatvesztés. És erről sehogy se tudom lebeszélni...

Just use supported C++, C#, Java, whatever.

Szerkesztve: 2020. 04. 05., v – 00:27

Kompozíció és kiterjesztés/leszármazás között órási különbség van. Még akkor is, ha memóriában történetesen ugyanúgy lennének reprezentálva. (Egyébként miért lennének?)

Feltételezem, hogy az általad javasolt megoldás továbbra is támogatná, hogy:

Inner inner2;
proba.inner = inner2;

assert(proba.i1 == inner2.i1);
assert(proba.i2 == inner2.i2);

De akkor azt is támogatnia kell, hogy:

Inner *inner = &(proba.inner);

assert(&(proba.i1) == &(inner->i1));
assert(&(proba.i2) == &(inner->i2));

Tehát elvileg azt is, hogy:

Inner *inner = &proba;

assert(&(proba.inner) == inner);

Ebből következik, hogy:

assert(&proba == &(proba.inner));

Ez eddig még talán érthető is, semmi nem zárja ki, hogy egy struktúra egy eleme önmagára mutasson, bár a típusokkal probléma van. De mi van akkor, ha:

typedef struct Inner1 {
  int i1;
} Inner1;

typedef struct Inner2 {
  int i2;
} Inner2;

typedef struct Outer {
  Inner1 inner1;
  Inner2 inner2;
  int o1;
  int o2;
} Outer;

Akkor annak is működnie kellene, hogy:

Inner1 *inner1 = &outer;
Inner2 *inner2 = &outer;

assert(inner1 != inner2);