- The C frontend now defaults to the GNU C23 dialect. Some code needs porting for this, see https://gcc.gnu.org/gcc-15/porting_to.html#c23 for more details. Some remaining C23 features have been implemented, as well as some new C2Y features.
- The C++ frontend now implements several further C++26 features, some missing C++23 bits, and defect report resolutions. The libstdc++ library now notably experimentally supports std and std.compat modules, more algorithms usable in constexpr functions, flat maps and sets, and std::format support for containers and other ranges.
- GCC now implements the Clang [[clang::musttail]] and [[clang::flag_enum]] attributes and their GNU counterparts with the same meaning for the C family language frontends. Support for new counted_by and nonnull_if_nonzero attributes has been added too.
- The Fortran frontend has experimental support for unsigned integers.
- GCC 15.1 has new COBOL frontend, so far supported only on a few 64-bit targets.
- OpenMP support now includes metadirectives, tile and unroll constructs, interop construct and dispatch construct.
- The vectorizer can now vectorize loops with early exits when array or buffer sizes aren't statically known. At -O2 can now vectorize some cheaply vectorizable loops with unknown tripcount.
- A hozzászóláshoz be kell jelentkezni
- 517 megtekintés
Hozzászólások
VIGYÁZAT! Törnek a korábbi kódok, ha explicit verziódefinícó nélkül fordítjátok, méghozzá nagyon nehezen debuggolható módon!
Ha van egy union, pl. "typedef union { char c; int i; } u;", és ezt globális változónál inicializálja az ember nullára, "u test = { 0 };", akkor minden szép és jó. NA DE! Ha lokális változóban van ugyanez, akkor csak 1 bájtot fog nullázni, a maradék 3 bájt random szemetet fog tartalmazni! Nem tudom, ki volt az a balfasz gcc fejlesztő, aki úgy gondolta, hogy ez a módosítás majd jó lesz bárkinek is... Nettó faszság, lássuk be.
typedef union { char c; int i; } u; u test1 = { 0 }; // ez jó, 4 bájtnyi nulla (globális, tehát .bss-be kerül) void balfasz_gcc_fejlesztes(void) { u test2 = { 0 }; // ez viszont nem, ez csak 1 bájtnyi nulla, a maradék továbbra is random szemét!!! (lokális, tehát a verembe kerül) }
Megoldás: "gcc -ansi" vagy "gcc -std=c17", és minden nyűg tovaszáll. Vagy explicit "memset(0)" minden union-t tartalmazó összetett lokális változóra, esetleg "gcc -fzero-init-padding-bits=unions", ha valamiért nagyon kell a C23...
- A hozzászóláshoz be kell jelentkezni
És az u testx = { 1 }; esetén mi történik? Az már a .data-ba megy, nem a .bss-be...
- A hozzászóláshoz be kell jelentkezni
És az u testx = { 1 }; esetén mi történik?
Természetesen hibát dob a fordító.
A C szabvány szerint a "{ 0 }" egy speciális inicializáló (ún. "universal zero initializer"), ami mindent nullára kell (kéne), hogy inicializáljon, akkor is, ha nem írod ki a tagokat.
Ezzel szemben a "{ 1 }", nem speciális, tehát helyesen vagy "{ .c = 1 }" vagy "{ .i = 1 }". Little endian gépeken mondjuk ugyanaz az eredmény, de big endian gépeken nagyon nem.
(C99 esetén már elfogadja a "{ 1 }"-et, ekkor ezt úgy veszi, hogy az első union tag kap értéket, tehát egy bájtnyi 1-es. Szerintem pont ezt szopták be, emiatt az első elemesdi miatt van az, hogy a "{ 0 }" csak az első tag méretéig nulláz most, holott a szabvány nem ezt mondja.)
Az már a .data-ba megy, nem a .bss-be...
A szabvány (81. oldal) szerint ha van részben inicializáció, akkor az explicit ki nem írt tagokat üresnek (azaz nullának) kell inicializálni a statikus tárolási osztály méretének erejéig (tehát C99-től is elvárás (lenne), hogy ha csak első tagot inicializálod az "{ 1 }"-el, akkor az egy bájtnyi 1-es utánni rész nulla legyen).
If there are fewer initializers in a list than there are members of an aggregate, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.
és (kiemelés tőlem)
If an object that has static storage duration is not initialized explicitly, it is initialized implicitly as if every member that has arithmetic type were assigned 0 and every member that has pointer type were assigned a null pointer constant.
Igen, a gcc 15.1 bugos és megsérti a C szabványt (még a C23-at is, bár azt is faszkalapok írták, így nem egyértelmű a szövegből, miért is kéne különbségnek lennie a "{}" és a "{0}" között. A C89-nél nincs ilyen probléma, ott feketén-fehéren leírták, hogy a "{0}" mit jelent).
A vicc az egészben, hogy a Clang-ban pont most javították, hogy az egész union-t nullázza, ne csak az első elem méretéig...
- A hozzászóláshoz be kell jelentkezni
Fentiekből nekem az is jön, hogy "javítás" lehet az, ha az unionban átrendezed a tagokat, és a legnagyobb méretűt teszed be elsőnek. (Gyakorlatban van jelentősége? Anno mikor még programozgattam (majdhogynem K&R) C-ben, elég hamar rászoktam erre, de már nem tudom minek hatására.)
- A hozzászóláshoz be kell jelentkezni
Azért ez meredek. Vajon sima structokra is ezt csinálja? Vagy csak az unionra pikkel? Végigolvasva a hozzászólásokat én arra tippelnék, hogy a structokra is ilyen hülyén viselkedik...
- A hozzászóláshoz be kell jelentkezni
Csináltam egy gyors tesztet, úgy tűnik, csak az union érintett, a struct nem. Szerencsére én minden projektemet "gcc -ansi" vagy "clang -ansi" kapcsolóval fordítom, ekkor nincs ez a probléma, csak C23 módban, ahol megengedett a "{}" is a "{0}"-n túl.
- A hozzászóláshoz be kell jelentkezni
Lokalis valtozoknal sosem volt default inicializalas, statikus globalisnal meg igen. Szoval ehelyett:
u test1 = { 0 };
en inkabb ezt irnam:
static u test1;
Garantalt a nullazas egesz tipusoknal, es nem kell rancolni a szemoldokot, hogy melyik mezot akartad torolni.
A lokalis valtozonal meg valszeg mukodik ez is:
u test2 = { .i = 0 };
Szerintem olvashatobb, egybol latszik, hogy mit akartal inicializalni, nem kell glibc-t linkelni a memset miatt vagy visszavaltani egy regi szabvanyra.
- A hozzászóláshoz be kell jelentkezni
"The Fortran frontend has experimental support for unsigned integers."
WoW
I have your source code, should I open it?
- A hozzászóláshoz be kell jelentkezni