Je jazyk C skutočne ťažký?

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #45 kdy: 03. 06. 2025, 12:01:13 »
Cely ten pripad s rotaci signed integeru mi prijde jako umele vykonstruovany priklad ktery jsem treba ja v praxi nikdy nemel,  nevim jak ostatni... Ale dava to smysl proc to tak je a tezko si predstavit ze by to melo byt jinak.
To je tvůj problém, že bitovým rotacím nerozumíš. Arithmetic right shift na signed čísle je jasně definovaný a je přesně dané, co to dělá a jsou na to CPU instrukce. Problém C je v tom, že přesně nedefinuje, co má rotace na signed čísle dělat. Standard dává možnost přeložit to jako aritmetický, nebo logický shift. Je to jeden z tisíce způsobů, jak se v C střelit do nohy, protože většína lidí předpokládá, že je to arimetický shift. Ale nemusí být, když to překladač C přeloží jako logický shift, je to taky podle C standardu v pořádku.

pouze u signed cisel, u unsigned je operace definovana exaktne... mozna bys mohl mene urazet a vice chapat... neni to zadny problem, protoze provadet takove operace na signed cislech je implementation defined z podstaty, protoze samotna signed aritmetika je implementation defined

ten kdo neco takoveho pouzije, musi mit duvod operovat se signed cisly a presne vedet co dela...

normalne clovek pouzije unsigned cisla a je vymalovano...


Re:Je jazyk C skutočne ťažký?
« Odpověď #46 kdy: 03. 06. 2025, 12:07:30 »
pouze u signed cisel, u unsigned je operace definovana exaktne... mozna bys mohl mene urazet a vice chapat... neni to zadny problem, protoze provadet takove operace na signed cislech je implementation defined z podstaty, protoze samotna signed aritmetika je implementation defined
Mohl bys prosím vysvětlit, co je neexaktního na signed arithmetic right shiftu? Je to naprosto běžná operace, která je definována exaktně. Říkat, že signed aritmetika je implementation defined, je opravdu hodně silné kafe. Není.

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #47 kdy: 03. 06. 2025, 12:14:40 »
pouze u signed cisel, u unsigned je operace definovana exaktne... mozna bys mohl mene urazet a vice chapat... neni to zadny problem, protoze provadet takove operace na signed cislech je implementation defined z podstaty, protoze samotna signed aritmetika je implementation defined
Mohl bys prosím vysvětlit, co je neexaktního na signed arithmetic right shiftu? Je to naprosto běžná operace, která je definována exaktně. Říkat, že signed aritmetika je implementation defined, je opravdu hodně silné kafe. Není.

Nikde neni v C garantovano jak jsou implementovana signed cisla. Dvojkovy doplnek je jen pouze jedna z moznosti, ackoliv bezna praxe. Takze -1 = 0xffffffff, klidne muze existovat architektura kde treba signed bit je na nultem bitu a nebo nejaka uplne jina exoticka reprezentace, proste to neni dano. A to je presne duvod proc je implementation defined right shift operace na signed integeru.

> Mohl bys prosím vysvětlit, co je neexaktního na signed arithmetic right shiftu?
Tak sam jsi tvrdil ze je implementation defined, tak co na tom mam vysvetlovat? Na dane architekture nevis jaky bude vysledek, dokud nevyzkousis jaka je implementace...

Sam

Re:Je jazyk C skutočne ťažký?
« Odpověď #48 kdy: 03. 06. 2025, 12:21:47 »
Je a neni. Imho pokud vezmes jazyk jako takovy ( bez knihoven ) tak te mohou potrapit v podstate jenom ukazatele. Opet zalezi na tom jestli clovek neco nekdy delal napriklad v asembleru, protoze pak je to chapani veci mnohem jednodussi. To co cinni psani programu v C "slozitym" je "tvoje odpovednost za vse" typicky alokace/dealokace pameti, aligment atd. C je krasny a mocny jazyk, imho nepravem opomijeny v dnesni dobe.

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #49 kdy: 03. 06. 2025, 12:31:29 »
Říkat, že signed aritmetika je implementation defined, je opravdu hodně silné kafe. Není.

Tak tady mas kavicku k obedu :D

Kód: [Vybrat]
UNIVAC 1100/2200 Series: These computers used one's complement arithmetic.
Similar to the VAX, they represented negative numbers by inverting all the bits of the
positive number.

CDC 6000 Series: The Control Data Corporation's CDC 6000 series, including models
like the CDC 6600, also used one's complement representation for signed integers.

IBM 7090/7094: These are examples of older IBM mainframes that employed
sign-magnitude representation for signed numbers, rather than one's or two's complement.
In the sign-magnitude system, the most significant bit is used as a sign bit, with the remaining
bits representing the magnitude of the number.

Takze pokud se bavine o bit shiftu unsigned integeru - tam je vse jasne, proste vezmes binarni reprezentaci a posunes vse o jeden bit doprava... Ale signed integer? Tady je kamen urazu. Protoze na kazde z techto architektur je stejny signed integer reprezentovan ruznym binarnim cislem, tak jaky ma byt presne vysledek bit shiftu?

Pokud stejny jako shift unsigned integeru, pak ztraci smysl arithmetic bit shift.
A pokud ruzny, tak timpadem musi byt implementation defined, protoze bud a nebo...
« Poslední změna: 03. 06. 2025, 12:33:06 od vrit »


Re:Je jazyk C skutočne ťažký?
« Odpověď #50 kdy: 03. 06. 2025, 12:31:42 »
Ale moznost jak detekovat preteceni v C existuje, clovek si muze lehce napsat funkci ktera mu rekne jestli vysledek scitani pretece nebo ne.
Oki, ukážeš mi jak lehce napsat takovou funkci pro signed inty?

Ve většině jazyků je definované, co se při přetečení signed intu stane. Když vím, že mi to při přetečení wrapne, tak se taková funkce dá opravdu relativně lehce napsat.

Re:Je jazyk C skutočne ťažký?
« Odpověď #51 kdy: 03. 06. 2025, 12:33:07 »
Nikde neni v C garantovano jak jsou implementovana signed cisla.
V posledním C23 standardu už je to garantované, signed čísla musí být implementována jako druhý doplněk. Měli šanci opravit right shift na signed číslech, ale neudělali to, v C23 je pořád tohle:

The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1/2E2 . If E1 has a signed type and a negative value, the resulting value is implementation-defined

Na dane architekture nevis jaky bude vysledek, dokud nevyzkousis jaka je implementace...
Ale to je problém jen C! Ostatní jazyky přesně specifikují, co right shift na signed číslech dělá a není to implementation defined, např. v Rustu je to vždy arithmetic shift.

Re:Je jazyk C skutočne ťažký?
« Odpověď #52 kdy: 03. 06. 2025, 12:39:32 »
normalne clovek pouzije unsigned cisla a je vymalovano...
Pokud člověk zrovna nepíše nějaký mission critical kód, kde má unsigned čísla zakázaná. Ano, tohle se opravdu dělá, protože nenápadná automatická konverze z intu na uint je recept na katastrofu.

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #53 kdy: 03. 06. 2025, 12:49:14 »
Ale moznost jak detekovat preteceni v C existuje, clovek si muze lehce napsat funkci ktera mu rekne jestli vysledek scitani pretece nebo ne.
Oki, ukážeš mi jak lehce napsat takovou funkci pro signed inty?

Ve většině jazyků je definované, co se při přetečení signed intu stane. Když vím, že mi to při přetečení wrapne, tak se taková funkce dá opravdu relativně lehce napsat.

Kód: [Vybrat]
bool add_will_overflow(int a, int b, int *result)
{
    if (((b > 0) && (a > INT_MAX - b)) ||   // positive overflow
        ((b < 0) && (a < INT_MIN - b)))     // negative overflow
        return true;

    *result = a + b;
    return false;                       // no overflow
}
« Poslední změna: 03. 06. 2025, 12:51:33 od vrit »

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #54 kdy: 03. 06. 2025, 12:57:20 »
Nikde neni v C garantovano jak jsou implementovana signed cisla.
V posledním C23 standardu už je to garantované, signed čísla musí být implementována jako druhý doplněk. Měli šanci opravit right shift na signed číslech, ale neudělali to, v C23 je pořád tohle:

The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1/2E2 . If E1 has a signed type and a negative value, the resulting value is implementation-defined

Na dane architekture nevis jaky bude vysledek, dokud nevyzkousis jaka je implementace...
Ale to je problém jen C! Ostatní jazyky přesně specifikují, co right shift na signed číslech dělá a není to implementation defined, např. v Rustu je to vždy arithmetic shift.

Tak to ale prece neni zadny neprekonatelny problem... napises si na to inline funkci, ktera to dela tak jak chces (pomoci castu na unsigned integer), a tu vsude pouzivas a je to... proc to je implementation defined jsem tu vysvetloval a resitelne to taky je, takze nevidim zadny problem.

Re:Je jazyk C skutočne ťažký?
« Odpověď #55 kdy: 03. 06. 2025, 12:59:44 »
Ale moznost jak detekovat preteceni v C existuje, clovek si muze lehce napsat funkci ktera mu rekne jestli vysledek scitani pretece nebo ne.
Oki, ukážeš mi jak lehce napsat takovou funkci pro signed inty?

Ve většině jazyků je definované, co se při přetečení signed intu stane. Když vím, že mi to při přetečení wrapne, tak se taková funkce dá opravdu relativně lehce napsat.

Kód: [Vybrat]
bool add_will_overflow(int a, int b, int *result)
{
    if (((b > 0) && (a > INT_MAX - b)) ||   // positive overflow
        ((b < 0) && (a < INT_MIN - b)))     // negative overflow
        return true;

    *result = a + b;
    return false;                       // no overflow
}
Supr, tohle vypadá že je i správně. :)

A co na to tazatel? Jak moc mu tohle přijde jednoduché? ;)

Re:Je jazyk C skutočne ťažký?
« Odpověď #56 kdy: 03. 06. 2025, 13:01:28 »
Ale moznost jak detekovat preteceni v C existuje, clovek si muze lehce napsat funkci ktera mu rekne jestli vysledek scitani pretece nebo ne.
Oki, ukážeš mi jak lehce napsat takovou funkci pro signed inty?

Ve většině jazyků je definované, co se při přetečení signed intu stane. Když vím, že mi to při přetečení wrapne, tak se taková funkce dá opravdu relativně lehce napsat.

Kód: [Vybrat]
bool add_will_overflow(int a, int b, int *result)
{
    if (((b > 0) && (a > INT_MAX - b)) ||   // positive overflow
        ((b < 0) && (a < INT_MIN - b)))     // negative overflow
        return true;

    *result = a + b;
    return false;                       // no overflow
}

Není to undefined behavior, když b == INT_MIN? Přesněji není -b undefined?

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #57 kdy: 03. 06. 2025, 13:13:19 »
Není to undefined behavior, když b == INT_MIN? Přesněji není -b undefined?

neni, proc by melo? :-) stejne jako 1-1 = 0 tak INT_MIN - INT_MIN = taky 0...
"to stejne" minus "to stejne" vzdycky bylo 0

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #58 kdy: 03. 06. 2025, 13:18:11 »
A co na to tazatel? Jak moc mu tohle přijde jednoduché? ;)

Tak co je uvnitr je podle me fuk, pro tazatele dulezite, ze takto to muze zavolat:

Kód: [Vybrat]
int result;
if(add_will_overflow(0x90000000, 0x900000000, &result))
{
    // handle overflow
}

Re:Je jazyk C skutočne ťažký?
« Odpověď #59 kdy: 03. 06. 2025, 13:25:16 »
Není to undefined behavior, když b == INT_MIN? Přesněji není -b undefined?

neni, proc by melo? :-) stejne jako 1-1 = 0 tak INT_MIN - INT_MIN = taky 0...
"to stejne" minus "to stejne" vzdycky bylo 0

Protože unární -INT_MIN je overflow. Nevím, jak binární. Ale třeba při použití zig cc (když Zigem kompilujeme C), tak takový program spadne na nedefinované chování i s binárním operátorem. Nebo, když to přeložím starým CompCertem, tak ten vypíše varování integer literal '2147483648' is too large to be represented in the enumeration integer type.