C operátor hogyan működik?

 ( asch | 2012. február 3., péntek - 17:39 )

Sziasztok!

Adott a következő C programrészlet:

uint16_t a=0x0100;
uint16_t b=0x0100;
uint32_t c;
c=a*b;

Mennyi lesz a c változó értéke?

Szerk.: 16 és 32 bites rendszereken különböző a végeredmény. A specifikáció megfelelő részére keresek linket.

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

65536

Biztos?

Biztos. Vizsgan ulsz? :D

----------------------
while (!sleep) sheep++;

Ha igen, akkor remélem megbukik. Ilyet kérdezni...

Nem vizsga, hanem egy programban találtam eltérő viselkedést PC-n és 8 bites mikrokontrolleren.

Sehol nem találtam meg az idevágó specifikációt, ami megadja, hogy egy műveletet milyen pontossággal kell elvégeznie a programnak, és abban biztam, hogy valaki beidézi az idevágó passzust :-).

Ahh, ott nem feltetlen 65535. Intte konvertalhat a szorzas, ami jelen esetben nem feltetlen nagyobb, mint 16 bit.

----------------------
while (!sleep) sheep++;

8bitesen 2 bájtos az int...

es mikrokontrollertol, illetve a fejleszto kornyezettol fugg ott (lasd PIC szeriak eleje)

hozza akartam ezt irni, de megtetted helyettem:)koszi

Nah igen, en is csak felkaptam a fejemet egy pillanatra;)
Nem effektive hozzad, de a temahoz tartozik es a kerdezonek:
- nezd meg mind a mikrokontroller, mind a fordito adatlapjat/doksijat, hogy milyen szo hosszt hasznal mihez.

Hát a 8 bites mikrovezérlő és C fordítóiról megban a véleményem. Hirdeti magáról a fordító, hogy ANSI C kompatibilis, ennek ellenére már az első órában sikerült írnom egy ANSI C kifejezést, amit nem tudott lefordítani.

Egyszóval több 8 bites mikrovezérlő fordító nem teljesíti maradéktalanul még a legalapabbnak számító ANSI C szabványt sem, bár azt állítja a gyártója, hogy ANSI C-t tudja.

én elgondolkoznék a kompatibilitás szó jelentésén

Az eredmény uint32-re castolódik, tehát nincs gáz.
0x0100*0x0100=0x1_0000.
Ez uint16 esetén 0x0000-ra csonkolódna, de uint32 esetén 0x0001_0000 lesz. (Az '_' csak ezreselválasztó jelölés.)

Bar tenyleg regen programoztam C-ben, de nekem ugy remlik, hogy signed int-te konvertalodik a szorzas eredmenye elso korben.

----------------------
while (!sleep) sheep++;

jelen esetben mindegy.

A kovetkezo tortenik amennyiben int szelessege kisebb mint 16 bit.

1. a es b int -re promotalodik.
2. a gep elvegzi a szorzast int ertekekkel
3. c erteket kap azaz az int eredmeny implicit typecast alltal 32 bitesre konvertalodik.

Azaz a 8 bite procinal fuggetlenul attol, hogy az int 16 vagy 8 bites, 16 biten vegzi el a muveletet. Ergo c erteke vaskos 0 -a lesz.

helyesen:
uint32_t c=(uint32_t)a * (uint32_t)b;

Ilyenkor 32 biten szamol.

mivel nem irta le kezdetektol fogva, hogy 8bites proci, ezert mindenki 32 bitesre asszocialt. Occam borotvaja, ugye.

ha atmel akkor bizony 0 (feltéve ha nem 32 bitest használsz)
sajnos szomorú tapasztalat. uint32_t már nem kezeli le tisztességesen.

dehogynem, csak kasztolni kell bőszen, mert uint16_t az int (vagy int16_t)?
A kérdésre a válasz: sajnos attól függ, hogy az architektúrán/fordítóban mi az int (ami a c-nél a default típus).

Ja, abban az esetben, ha az int legalabb 32 bites. Mert ugye integer promotion tortenik a szorzasnal.

Es mint a kódból láthatjuk, igen, 32b-es változó.

Nem a valtozo szelessege erdekes, hanem a sizeof(int) eredmenye, azaz a proci szo szelessege.

Mikrokontrollereken (és nagyon régi cpu-kon) kivűl van olyan aminek kevesebb a szószélessége mint 32-bit?

------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.

DSP-n, CPLD-n és FPGA-n, illetve csak 16:53kor írta le, hogy nem csak 32biten, hanem 8bites uC-n is kérdés az aritmetika.

Igaz. Bár fpga-n, és cpld-n (lehet hülye kérdés) a szóhosszúságot nem programozó deklarálja?

------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.

nem hülye a kérdés, és igen. Illetve megszorítás a cuccban levő összeadó, szorzó méretei.

reméljük:)

Akkor talán keressük meg a helyes választ.

Először is, az uint16_t és az uint32_t opcionálisan típusok, egy C99 implementációnak nem kötelező támogatnia ezeket. (ISO C99 7.18.1.1 Exact-width integer types.) Ha azonban egy implementáción léteznek ezek a típusok, akkor kötelező nekije ezeken a typedef-eken is elérhetővé tennie.

Ezután vesézzük ki a szorzást (ISO C99 6.5.5 Multiplicative operators). Először is, a két operanduson végrehajtjuk a usual arithmetic conversion-öket, amelyeknek a legelső lépése jelen esetben a default integer promotions mindkét operanduson. (Lásd 6.3.1.8 Usual arithmetic conversions, valamint 6.3.1.1 Boolean, characters, and integers, 2. bekezdés.)

Ha az int olyan, hogy tudja ábrázolni a teljes uint16_t értékkészletet, akkor mind a, mind b int-re konvertálódik (mindegyik ugyanonnan indul, uint16_t-ről). Egyébként pedig mindkettő unsigned int-re. Az unsigned int típus minimális maximuma 65535 (ISO C99 5.2.4.2.1 Sizes of integer types <limits.h>), tehát az feltétlenül tudja ábrázolni az uint16_t teljes értékkészletét; ha azonban az int-is képes erre (ami platformfüggő), akkor int-re megyünk.

Az uint16_t konverziós rangja megegyezhet az int-ével, megegyezhet a short-éval, megegyezhet a char-éval, illetve takarhat egy extended unsigned integer típust valahol az int rangja alatt, azonban mind a négy esetben (az előző bekezdés szerint) int-re vagy unsigned int-re "lép elő" mind a, mind b. Az uint16_t nem lehet magasabb rangú az unsigned int-nél, mert ahhoz vagy long rangúnak kellene lennie (amit az értékkészlete nem tesz lehetővé), vagy az unsigned int-nél szélesebb extended típusnak kellene lennie, amit ismét a tartománya nem tesz lehetővé.

Mivel így két azonos típusú operandusunk van (vagy int mindkettő, vagy unsigned int -- jelöljük ezt a promotált típust most T-vel), azért a usual arithmetic conversion-ök mást nem írnak most elő, végrehajtjuk a szorzást.

Ha a szorzás eredménye T típusban ábrázolható (figyelem! itt még nincs szó konverzióról, csak arról, hogy maga az eredmény előállítható-e a T típusban!), akkor minden rendben van.

Ha nem, akkor már számít, hogy T (= a promóció eredménye) signed int vagy unsigned int lett-e. Ha az utóbbi, akkor semmi gond; a matematikai szorzatot modulo (UINT_MAX+1) redukáljuk. Ha T signed int volt, akkor sajnos a túlcsordulás nem definiált, vége a dalnak, innentől bármi megengedett az implementáció számára. (ISO C99 6.2.5 Types, 9. bekezdés, illetve 6.5 Expressions, 5. bekezdés.)

Tegyük fel, hogy megvan az eredmény (T típusban, ami int vagy unsigned int a fentiek szerint). Ezt az értéket az értékadás során konvertáljuk uint32_t-re. (ISO C99 6.5.16.1 Simple assignment, 2. bekezdés) Mivel az uint32_t előjel nélküli típus, azért a túlcsordulás pontosan definiált.

(Figyelem! Ez a modulo (UINT_MAX+1) redukció nem ugyanaz, mint a fenti! A vonatkozó rész itt a 6.3.1.3 Signed and unsigned integers, 2. bekezdés. A fentebbi esetben egy szorzás (matematikai művelet) kiértékelése során az a kérdés kerül elő, hogy az eredmény egyáltalán előállítható-e az adott típusban. Túlcsordulás esetén előjel nélküli típusnál redukció, előjelesnél definiálatlan a viselkedés. Itt viszont egy meglévő értéket konvertálunk másik típusra. Túlcsordulás esetén előjel nélküli céltípusnál ugyanolyan a redukció, mint előbb, azonban előjelesnél sem definiálatlan a viselkedés, hanem vagy implementáció által definiált (= kötelezően dokumentálandó) a numerikus végeredmény, vagy egy impl.def. (= kötelezően dokumentálandó) szignál generálódik.)

Két gyakori kiosztást megnézve (padding biteket mindenhol kizárom, és kettes komplemenst tételezek fel a negatív ábrázoláshoz):

  • 8 bites char, 16 bites short, 32 bites int: a promóció signed int-re történik. Ha a szorzat nem ábrázolható, akkor undefined behavior. Ez a legtöbb platformon azt eredményezi, hogy a kilógó biteket levágjuk, ami marad, az pedig kettes komplemens ábrázolás szerint lehet negatív is (a sign bit függvényében). Ez történik pl. x86(_64) GNU/Linux-on. A topiknyitóban megadott értékekkel természetesen nincs túlcsordulás, az eredmény 0x10000.
  • 8 bites char, akárhány bites short, 16 bites int: az előléptetés nem látszik szükségesnek (az uint16_t az unsigned int typedef-je), de ha a platform beteg volna, és valamilyen extended típust használna uint16_t-re, akkor a promóció unsigned int-re történik. (6.3.1.1 Boolean, characters, and integers, 1. bekezdés.) A szorzás definiált, eredménye nulla.
  • 16-nál kevesebb bit az int-ben. Ez nem C99-konform platform.

Aki ezt nem tudja fejből, vagy nem tudja megnézni a szabványban (vagy egy ahhoz nagyon közeli draft-ban), az nagyon óvatosan írjon C programot, mert tele lesz undefined (de minimum implementation defined) behavior-rel. Vagy legalábbis szigorúan ragaszkodjon egy adott platformhoz (hardvert és fordítót beleértve).

Vagy használjon lintet. (Ami elvileg pont az ilyen gusztustalan platformfüggő dolgok észrevételéért vol felelős.) De gondolom ma a GCC / CLang+LLVM / mimás? is rendelkezik olyan opcióval, ami ilyen lint-szerű működést eredményez.

vuuáááuuuu. grat. szép okfejtés.

Köszi! Szép munka!

Kimerítő volt :)

Nem értem, miért kell egy 8 bites mikrokontrollert c-ben programozni.... Tipikus gépi kódú feleadat.
Máshogy elveszel a szabványok, túlcsordulás és hasonlók között.
---
Repeat after me: I Will Use Google Before Asking Stupid Questions...

A produktivitás miatt. Meg nem lehet minden mikrovezérlő assemblyjét fejben tartani.

De milyen már az, hogy valaki össze akar szorozni két számot, az ábrázolási tartományokba a tényezők is beférnek, és a szorzat is belefér, de az eredmény mégsem lesz megfelelő: én elvárom a XXI. században, hogy egy szorzás eredménye vagy rendesen álljon elő, vagy OverFlowException keletkezzen.

Fuszenecker_Róbert

jávás vagy, ugye?

le se tagadhatna :)

Nem biztos, hogy baj az; feladathoz eszközt :)

Egyébként:

De milyen már az, hogy valaki össze akar szorozni két számot, az ábrázolási tartományokba a tényezők is beférnek, és a szorzat is belefér, de az eredmény mégsem lesz megfelelő

Hát ez az: a platformtól függően a szorzat nem biztos, hogy belefér. A Java ilyenkor kivételt dob (vagy használsz BigInteger-t). A C viszont azt mondja:

  • Trust the programmer.
  • Don't prevent the programmer from doing what needs to be done.
  • Keep the language small and simple.
  • Provide only one way to do an operation.
  • Make it fast, even if it is not guaranteed to be portable.

A fordító úgy áll hozzá a programodhoz, hogy te tudod, mit csinálsz :)

feladathoz eszközt, na de ne rosszat :-)

És igen, a program azt csinálja amit én akarok, ne azt amit gondolok :-)
Ha nem azt csinálja, az az én hibám, nem a programé.
"Felelős vagy a rózsádért."

A Java sima integer aritmetika túlcsordulásra nem dob exception-t, hanem úgy működik, mint C-ben - a tetejét az eredménynek levágja. 0-val osztásra ad csak axception-t. Integer aritmetikára a processzor utasításait használja. Ráadásul elégé hatékony kódot csinál a JIT compilere. Ha integer utasításokat kell ciklusban végrehajtani, arra kb olyan jó, mint a C nyelv maga.

Abból, hogy a C platformfüggően értelmezi a leírt programkódot semmilyen teljesítmény nyereség nem származik, hanem csak rengeteg hiba.

A C-ben pont az a lenyeg, hogy nem gondolkozik helyetted. Igy nem pakolja tele a forditott kodot mindenfele szemettel, es lehet benne hatekonyan mukodo programot irni. (Cserebe ismerni kell rendesen a nyelvet es az adott platformot.) A C-re szeretek ugy gondolni mint egy hordozhato assembly-re, mert kb. az is.

" A C-re szeretek ugy gondolni mint egy hordozhato assembly-re, mert kb. az is."
Nemcsak kb. :) A C a hordozhato assembly, az eredete szerint is.

Azert mondom, hogy csak kb., mert azert lenyegesen kenyelmesebb, viszont kevesebb szabadsagot ad.

Nem, C#-os. És szeretem azt, hogy a feladatra koncentrálhatok, nem az eszközre.
Engem azért fizetnek, hogy megoldjak egy feladatot határidőre, és nem azért, hogy a nyelvvel szopjak.

Fuszenecker_Róbert

Valakinek a C# futtatokornyezetet is meg kellett irnia. O szopott helyetted is :) + van ahol eleve nem jarhato ut a C# meg az akarmi mas, mert nem elerheto az adott platformra vagy a kod sebessege a fontos.

+1
Valahol volt topicban, hogy EJB3 izével akart lekérdezni ütemezve plc-ket. Most csak azért felrakni egy glassfisht, hogy egy cronjobot emuláljon? JavaEE-ben Singletonnal szopni, hogy a serialport kezelés ne akadjon össze?
Hova jutott ez a világ...

"Valakinek a C# futtatokornyezetet is meg kellett irnia." -- Éljen soká, aki bevállalta :-) Viszont ezzel megspórolt pár ezer mérnökórát a többi programozónak.

"van ahol eleve nem jarhato ut a C#" -- természetesen, a C#/Java/Python/PHP/sh sem csodaszer. De ahol választhatok, ott a legmagasabb absztrakciós szintet fogom választani (feltéve, hogy a futási sebesség és a fogyasztás kevésbé szempont). Mikrovezérlőn én is C-znék vagy C++-oznék. Ha van operációs rendszerem, és azon elmegy a keretrendszerem, akkor azt fogom választani. Miért írjak újra egy kódot, amit előttem valaki már megírt, és ami sokkal fontosabb: letesztelt.

De azt nekem senki se mondja, hogy a C kód fent említett viselkedése normális. Kevés kivételtől eltenintve mindenki azt várná, hogy az eredmény 0x0001_0000.A józan ész ezt doktálja.

Fuszenecker_Róbert

Beszéltem mindenkivel, és elmagyaráztam neki, hogy elég logikus, hogy két uint16_t szorzata is uint16_t legyen, ha nem ezt akarjuk, akkor még a szorzás előtt kell elvégezni a típusátalakítást.

+1
Ha két almát berakok egy ládába, akkor elvárom, hogy a ládában is alma maradjon, a belerakás után is.

+1

----------------
Lvl86 Troll

Ezek szerint én vagyok az egyetlen, aki mindig jól akarja elvégezni a szorzást.
Mindig eredményt akarok, és mindig helyes eredményt akarok.

Fuszenecker_Róbert

Nem, de azért általában az ember tudja, hogy mit mivel akar szorozni.

----------------
Lvl86 Troll

és milyen doménen.

"És szeretem azt, hogy a feladatra koncentrálhatok, nem az eszközre."

Ezt hívják tipikus OOP hozzáállásnak. a nyelv nyalja ki a seggem, amit nem tud megcsinálni ara szükség sincs, problémával akarok foglalkozni nem a nyelvvel szopni...bezzeg amikor Linq-ben nem tudnak valamit megcsinálni, hozzám jönnek sírni. Az nem a nyelvvel szopás? Vagy más thread-ből UI-t basztatni. "Minek az a DispatcherObject? hámérnem oldja meg a háttérben? deszarez!". Jellemző...

"bezzeg amikor Linq-ben nem tudnak valamit megcsinálni" -- A LINQ használata és két szám összeszorzása között van egy kis különbség: az előbbi nem kötelező, az utóbbit viszont elég nehéz mással pótolni.

"Vagy más thread-ből UI-t basztatni." -- csakhogy erről tudunk. De a 256 × 256 = 0 dolog viszont azért került elő, mert a topiknyotó nem tudott mit kezdeni a jelenséggel.
Egy jóérzésű fordító legalább egy warningot dobhatott volna.

Fuszenecker_Róbert

viszont lehet, hogy pont ezt a viselkedest varod el.

Szerintem meg nincs különbség. Aki az elsőrendű logikát nem érti, az ne akarjon összeadni se, mikroprocesszoron.

Miről tudunk? Odajön/levelet ír/felhív skypeon és megosztja a desktopját/odahív(!!!), hogy ez elszáll. De oda is van írva az exceptionbe, hogy invocation on another thread (vagymi).

És ha én implicit modulo-t akarok a szorzásomhoz? mennyivel hatékonyabb már az (u8)256 * (u8)256 mint a ((u32)256*(u32)256)%256? Na?

"Szerintem meg nincs különbség. Aki az elsőrendű logikát nem érti, az ne akarjon összeadni se, mikroprocesszoron." -- ügyesen lehülyézted az olvasók felét.

"De oda is van írva az exceptionbe, hogy invocation on another thread (vagymi)." -- de legalább oda van írva, hogy hol keresd a hibát. A topiknyitónak még ennyi támpontja sem volt.

"És ha én implicit modulo-t akarok a szorzásomhoz? mennyivel hatékonyabb már az (u8)256 * (u8)256 mint a ((u32)256*(u32)256)%256? Na?" -- lehet csinálni olyan processzort, ahol az utóbbi kifejezés 1 órajel, az első meg 100. Na és? Mit bizonyít ez? Mert a C nyelvi kifejezés és annak futási ideje között semmiféle összefüggés nincsen.

Fuszenecker_Róbert

" lehet csinálni olyan processzort, ahol az utóbbi kifejezés 1 órajel, az első meg 100. Na és? Mit bizonyít ez? Mert a C nyelvi kifejezés és annak futási ideje között semmiféle összefüggés nincsen."

De van, ha tudod, hogy az egyik kifejezesbol gyorsabb kod lesz arra a procira amire dolgozol. Persz, oldjon meg mindent a fordito... :D (es maris fel ora lesz egy par soros program forditasa, a fordito fejlesztesi koltsege meg az Apollo programeval fog vetekedni)

"De van, ha tudod, hogy az egyik kifejezesbol gyorsabb kod lesz arra a procira amire dolgozol." -- akkor máris nem "hardverfüggetlen assembly" :-)

Azért vagyik nyűgös a túlcsordulások nem jelzése miatt (elfogadom azt is, ha bevallja a kütyü, hogy nem tudja megcsinálni), mert egyszer implementáltam egy Viterbi-algoritmust, ami ugye egy hibajavító megoldás. Szépen működött is, ki is javította a hibák nagy részét. Csakhogy (mert a gyanúm utólag bebizonyosodott) időnként túlcsordult a változóm, emiatt pedig nem javított ki olyan hibákat, amelyket 1 napi debugolás és kódhegesztés után már igen. És mivel elvileg sem volt lehetőségem a túlcsordulásokat figyelni (a C kitalálói nem adnak nyelvi elemet a Carry bit figyelésére -- hardverfüggetlen módon legalábbis nem: a kód PC-n készült, de ARM Cortex-M3-on futott végül [akkoriban még az volt a csúcstechnológia]), eléggé trükkös módon kellett megoldanom a problémát. Persze megoldottam, és örült a lelkem.

Mindenesetre a hosszúra sikerült beszélgetésünkből világosan látszik, hogy más-más iskola tanait hirdetjük. Neked hardverközpontúbb a gondolkodásod, nekem meg eredményközpontúbb (az én matematikám szerint a 256×256 = 0 teljesen hibás eredmény). Nem vagyunk egyformák. Még jó, kicsit egysíkú lenne a világ.

Fuszenecker_Róbert

"hardverfüggetlen assembly"

Pont ezert engedhetoek meg az ilyen kulonbsegek. Lehet benne sok odafigyelessel hordozhato kodot irni, de ugyanakkor ki lehet hasznalni a hw specifikus dolgokat is.

Köszi a bókot. De a burkolt reductio ad hitlerumot észrevettem ám.

A HOL nincs oda irva az uzenetbe, csak az, hogy "másik threadbe akartál belehívni, ezért a szoptálcetli ma a tiéd". a hol az a stack traceben van benne, és ugye release kódban nincs debug info (ugye?), igy nincs sorszámod a stack trace-ben. Ugye. Ja, majd csinálj egy mikrofelmérést, hogy tudják-e az emberek, hogy mik vannak az Exception osztályban a Message-n kívül, meg fogsz lepődni.

Lehetne, de a mai processzorok az előbbit részesítik előnyben :-)

És szeretem azt, hogy a feladatra koncentrálhatok, nem az eszközre. Engem azért fizetnek, hogy megoldjak egy feladatot határidőre, és nem azért, hogy a nyelvvel szopjak.

Teljesen jogos. Felesleges C-hez nyúlni, ha nem elkerülhetetlen.

Igen, köztudott, hogy a C az egyetlen nyelv, ahol az aritmetikai műveletek túlcsordulhatnak ;)

Nyilván :)

Igen, köztudott, hogy a C az egyetlen nyelv, ahol az aritmetikai műveletek túlcsordulhatnak ;)

Most mellékes, hogy hány nyelvben csordulhatnak még túl, és hogy hogyan.

Az a fontos, hogy a nyelv saját fogalmai és a feladattér ("domain") fogalmai között mekkora a különbség. Ha nincs nyomós ellenérvünk, akkor olyan nyelvet érdemes választani, amely a feladattérhez a lehető legközelebb van (DSL, vagy kényelmes/biztonságos általános nyelv). A C valóban borotvaéles és gyakran igen kevéssé intuitív, ebben a tekintetben azonban csak egy példának szántam.

De azt nekem senki se mondja, hogy a C kód fent említett viselkedése normális. Kevés kivételtől eltenintve mindenki azt várná, hogy az eredmény 0x0001_0000.A józan ész ezt diktálja.

Ezzel mindenesetre értek egyet. A C a saját alkalmazási területén közel tökéletes. Ha az eredmény pontos ábrázolása elsődleges, akkor viszont olyan nyelvet kell választani, ami ezt helyből akarja (nemcsak "tudja"), vagy megfelelő függvény-/osztálykönyvtárat kell használni (C-ben, C++-ban, Java-ban stb).

Én például többnyire kerülöm a C++-t. Nagyon is valós gyakorlati hátrányai vannak, a programozása közben pedig iszonyatos mennyiségű buktatóra kell figyelni. Minden, ami a C-ben macerás, közel ugyanolyan macerás C++-ban is, de bejön még rengeteg új fogalom (többsége automatizmus, ami a "háttérben" zajlik: kivételkezelés, virtuális metódusok, különösen többszörös öröklésnél rejtett mutató-machináció, destruktorok, template-ek), emellett a stílus fontossága minimum egy nagyságrenddel nagyobb. Nincs továbbá semmilyen műszaki szabvány, amely a C++-t mondjuk a UNIX rendszerprogramozással ötvözné, ennek ellenére minden szépreményű C++ programozó azzal kezdi, hogy ír egy C++ IO/threading library-t, kivételekkel, örökléssel, wrapper class-okkal, aztán csak néz, hogy hányféleképpen tud fejreállni.

A C++-nak sokkal nagyobb a kifejezőereje, ezért sokkal nehezebb is rendesen használni. Nagyobb nyelvi odafigyelést igényel, a stílus/tervezés (mint említettem) kritikus -- sokkal inkább "mit ne használjunk", mint "mit használjunk" --, rengeteg plusz fogalmat kell bebiflázni (vagy folyton megnézni) a szabványban. Akik dobálózni szoktak a C++ programozásával, azok többnyire nem ismerik a szabványt.

(Nem tudok mit mondani a C++-ról, nem ismerem, de valószínűleg nagyon jó valamire az is.)

En pl. pont a hatterben torteno dolgok miatt nem szeretem a C++-t. Ugyan olyan kenyelmetlen mint a C, de ugyan ugy nem tudod mi lesz a kododbol mint egy magasabb szintu nyelvnel. (Mondom ezt ugy, hogy egyebkent a C a kedvenc nyelvem.)

Mondjuk azért C#-al példálózni mikrokontrolleres környezetben... na, az is megér néhány InvalidArgumentException-t.

----------------
Lvl86 Troll

Nono, .NET Micro Framework nagyon nyomul ilyenekre is... (konkrétan nálunk a tanszéken vannak ilyen témák, hogy portolni adott MCU-ra...). Java dettó (ott meg a JOP érdekes projekt).

Más kérdés, hogy számomra is meglepő volt. Meg furcsa. Meg berzenkedem tőle. De van.

Igen, tudom, hogy van .NET MF, de amennyire néztem, hw igénye számomra nagyobbnak tűnt, mint amit egy átlag mikrocontrollernek gondolnék. Igaz, nem túlzottan értek hozzájuk, szóval... :)

----------------
Lvl86 Troll

Meg nem lehet minden mikrovezérlő assemblyjét fejben tartani.

Te ugye életedben nem írtál még valódi programot assemblyben?

Sosem. Nem programoztam 1995 és 1997 között assemblyben, nem kezdtem el egy operációs rendszert írni és nem írtam egy (csúnya, de működő) grafikus felületet sem.
Sosem láttam még assemblyt. És C-t sem. C++ meg aztán végképp nem.
Fogalmam sincs, hogy mikor számít a kód hatákonysága, és mikor a programozó produktivitása.

Fuszenecker_Róbert

lehet mikrovezerlot .net-ben is programozni, csak nem minden feladathoz lesz megfelelo

--
NetBSD - Simplicity is prerequisite for reliability

Nagyon szép összefoglalás.

Egyébként javaslom a MISRA-C szabályok tanulmányozását a topicindítónak, sokat segíthet, elvben az ilyen huncutabb dolgok elkerülésére kiváló.

Ugyanennek (vagyis a túl későn végzett típus-váltásnak) egy változata:

rossz:

int a= 1;
int b= 2;
double d= a/b;

jó:

int a= 1;
int b= 2;
double d= (double)a/b;

kedvenc kérdéstípusom tesztekben :)

az erjedt gyumolcsnek is van jo vegeredmenye

---
Egy jól megállapított probléma félig megoldott probléma.
- Charles Kettering

A C fordító a fenti példa esetén egyébként a C-s logika szerint rendben dolgozik:

32 bit = 16 bit * 16 bit
ami valójában
32 bit = (32 bitre kasztol az eredményregiszter miatt) (16 bit * 16 bit)
Tehát ez a fenti 0x100-as értékek esetén 0-át hozza eredményül.

Ha bármelyik operandus 32 bites, akkor
32 bit = 32 bit * (32 bitre kasztol)16 bit

Ezt úgy is elérheted, ha
c = (uint32_t)a * b;

Azaz csak az "a" 32 bitesre való átalakítása már 32 bites aritmetikába rántja a "b" operandust is.

És hogy miért így csinálja? Mert így gyors, hiszen csak egyszer kasztolt 32 bitre, az aritmetika viszont 16 bites maradt. Ha a 16 bites aritmetikával való gyors számolásról a programozó látja, hogy nem fog elférni 16 biten, akkor a programozónak kell figyelmeztetnie a C fordítót, hogy 32 bites aritmetikával dolgozzon végig és ne csak a végén egyszer konvertáljon.

A C ezért nehéz nyelv. Semmi automatizmus, semmi plusz vizsgálat. A programozó amit leír, az hajtódik végre. Ellenben GYORSAN!