C3 som podrobnejšie neštudoval, ale všeobecne platí, že je nutné zabezpečiť, aby sa dalo v jazyku vyjadriť všetko potrebné a aby sa pri tom nemýlil parser. Takže pri návrhu jazyka mohlo ísť o kompromis medzi estetikou a stručnosťou pri zachovaní jednoznačnosti vyjadrenia.
Niekto tu nedávno písal niečo v zmysle, že lambdy v C++ sú ako zápis hnusné. No áno, sú ukecané, ale zas parser vie presne, čo má. A neopakuje sa most vexing parse a ani to, špeciálne v prípade C++, nekoliduje s historickým kódom.
On ten UB u overflow integeru je v C/C++ je docela užitečný. Například
(i+1 > i) je vždy true.
Je třeba si uvědomit, že pokud někde je něco definované, nelze to optimalizovat. Takže pokud je zadefinováno, že int je dvojkový doplněk, pak to musí být i tam, kde se používá jiný systém (například pokud se int simuluje na fpu, tam dvojkový doplněk není a přetečení se pak musí ošetřovat)
A mezi tato temná zákoutí patří i nedefinované chování (undefined behavior) neboli krátce UB. ... Typicky jsou tyto oblasti ve specifikaci jazyka popsány buď vágním způsobem, nebo je (v lepším případě) přímo specifikováno, že se určitá programová konstrukce může chovat v závislosti na implementaci.
Tohle mi moc nedává smysl. Standard jazyka definuje chování programu pouze za splnění určitých podmínek. To, že při porušení těchto podmínek není chování definováno (standardem), z toho implicitně vyplývá, a není potřeba to explicitně zdůrazňovat. Není na tom nic "vágního". Překladače tak nemusí řešit, jak se program má chovat při porušení podmínek daných standardem, a díky tomu mohou generovat optimální strojový kód za předpokladu jejich splnění.
Pokud je specifikováno, že se má program chovat v závislosti na implementaci, tak se nejedná o nedefinované chování, ale o chování definované implementací (implementation-defined behavior), což je poměrně podstatný rozdíl.
19. 11. 2025, 08:31 editováno autorem komentáře
Huh, ten příklad s coredumpem Céčka, co vrací pointer na stack mě zaujal, jak je to možné (však sice tam bude nějaká blbost, ale page pro stack je namapovaná pořád)
No, tohle mě překvapilo, ono to vrací NULL:
Dump of assembler code for function foo:
0x0000000000401126 <+0>: push rbp
0x0000000000401127 <+1>: mov rbp,rsp
0x000000000040112a <+4>: mov DWORD PTR [rbp-0x4],0x2a
0x0000000000401131 <+11>: mov eax,0x0
0x0000000000401136 <+16>: pop rbp
0x0000000000401137 <+17>: ret
malá modifikace už necoredumpuje - zajímavě řešené UB v céčku.
int* foo()
{
int a = 42;
int *b;
b = &a;
return b;
}
Dump of assembler code for function foo:
0x0000000000401126 <+0>: push rbp
0x0000000000401127 <+1>: mov rbp,rsp
0x000000000040112a <+4>: mov DWORD PTR [rbp-0xc],0x2a
0x0000000000401131 <+11>: lea rax,[rbp-0xc]
0x0000000000401135 <+15>: mov QWORD PTR [rbp-0x8],rax
0x0000000000401139 <+19>: mov rax,QWORD PTR [rbp-0x8]
0x000000000040113d <+23>: pop rbp
0x000000000040113e <+24>: ret
End of assembler dump.
(překládáno s -O0)