Kysymys:
Yksinkertainen kertovika
Huskarnov
2019-02-05 15:36:59 UTC
view on stackexchange narkive permalink

Seuraavan koodin suorittaminen antaa tulokseksi aina -511, tein monia testejä, ja näyttää siltä, ​​että tulokset ovat oikeita välillä 0 * 0 - 181 * 181, sen lisäksi tulokset ovat epänormaalit, kokeilin monia tyyppejä z: lle muuttuja (int, pitkä, kelluva) ilman menestystä, onko mitään ideaa? Käytän Arduino Unoa.

  long z = 0; void setup () {Serial.begin (9600);} void loop () {z = 255 * 255; Sarjaprintln (z); viive (200);}  
Vihje: Kokeile "z = 255 * 255L;" tai "z = 255 * (pitkä) 255;"
Minä tein. @MikaelPatel Työskentelin todella, voisitko selittää syyn tähän, ja onko vastaavia tapauksia muillekin?
Tämä "vika" on yhtä vanha kuin ohjelmointi. Kun kirjoitat "255", kääntäjä luo "kokonaisluvuvakion", jonka arvo on 255. Kun kerrot 255 255: llä, kerrot kaksi "kokonaisluvuvakiota" ja sopimuksen mukaan tällaisen kertolaskun tulos on "kokonaisluku". Sitten heität sen implisiittisesti pitkäksi tehtävää tehdessäsi. Kun kerrot "255" luvulla "255L", kerrot itse asiassa "kokonaisluvuvakion" luvulla "pitkän vakion" ja tällaisen kertolaskun tulos on "pitkä". Näet samanlaisen ongelman kirjoittaessasi "float z = 1/5". Tulos on "0", koska kokonaislukujako johtaa kokonaislukuun, joka myöhemmin heitetään kellumaan.
Viite: https://gcc.gnu.org/wiki/avr-gcc on kaikki tarvitsemasi tiedot AVR GCC-kääntäjälle. Kaikki liittyy 1) tietyn kohteen "int" lukualueeseen ja 2) vakiolausekkeiden kääntäjän arviointiin.
@MikaelPatel Sinun tulisi vastata kysymyksiin sen sijaan, että kirjoittaisit niistä katkelmia kommenttiosaan.
Kaksi vastused:
Kwasmich
2019-02-05 15:51:25 UTC
view on stackexchange narkive permalink

Ei, tämä ei ole vika. Käytät kääntöaikavakailauseketta, joka on signeerattu int , ellei toisin mainita. Siksi voit edustaa vain numeroita välillä -32768 - 32767. 255 * 255 = 65025 -laskennasi ylittää alueen. Näin näet ylivuotoa. C / C ++ -standardissa allekirjoitettujen tyyppien ylivuoto on itse asiassa määrittelemätöntä käyttäytymistä. Tämä tarkoittaa, että kääntäjä saa tehdä mitä tahansa näyttämättä oikeaa vastausta pysähtyäkseen ja sytyttääkseen tulen. Vain allekirjoittamattomilla tyypeillä, joiden koko tunnetaan, kuten uint16_t , on hyvin määritelty ylivuotokäyttäytyminen. Sinun tulisi mainita oikeanpuoleinen laskenta allekirjoittamattomaksi tyypiksi näin:

  z = 255U * 255U;  

Tällä tavalla kerrot kääntäjälle aikomuksesi ja älä laske "Määrittelemätön-Käyttäytyminen-Maa".

@Juraj Oikein, luulin, että se oli allekirjoitettu 16-bittisenä aivan kuten `int`. Mutta jälkimmäinen on totta. Käännösajan vakiot ovat `allekirjoitettuja int`, mikä on 16 bittiä. Joten tehtävän oikea puoli on ongelma.
`kääri 'ei kuulosta oikealta - mutta tiedän mitä sanot
Michel Keijzers
2019-02-05 15:51:16 UTC
view on stackexchange narkive permalink

Olettaen, että pitkä on 4 tavua, sen pitäisi toimia.

Jos jotenkin pitkä tyyppi on vain 2 tavua, tai (todennäköisemmin) käytit toista tyyppiä tai siinä on väärä define / typedef, ja se on allekirjoitettu pitkä (oletus, jos et käytä allekirjoittamatonta avainsanaa), arvoalue on -32 768 - 32 767 ja 255 * 255 = 65 025, joka on alueen ulkopuolella.

Voit siis ensin yrittää käyttää unsigned long .

pitkä on -2 147 483 648 - 2 147 483 647
Allekirjoittamattomalla pitkällä tuloksella tulee: 4294966785.
Kwasmichin vastaus on oikea
@Juraj - yksi lyhyt: s
@Juraj Olen niin kauan määritelty jotenkin 2 tavuksi.
se ei ole. Kwasmich selittää


Tämä Q & A käännettiin automaattisesti englanniksi.Alkuperäinen sisältö on saatavilla stackexchange-palvelussa, jota kiitämme cc by-sa 4.0-lisenssistä, jolla sitä jaetaan.
Loading...