EOF-merkin (tiedoston loppu) tallentaminen merkkityyppiin
On helmikuu 18, 2021 by admin Luin Dennis Ritchien ”s C-ohjelmointikieli kirja, jota int
on käytettävä muuttujan pitämään EOF –, jotta se olisi riittävän suuri, jotta se voi pitää EOF-arvon – ei char
. Mutta seuraava koodi toimii hyvin:
#include<stdio.h> main() { char c; c=getchar(); while(c!=EOF) { putchar(c); c=getchar(); } }
Kun ei ole enää syötettä, getchar
palauttaa EOF: n. Ja yllä olevassa ohjelmassa muuttuja c
, jolla on char-tyyppi, pystyy pitämään sitä onnistuneesti.
Miksi tämä toimii? Kuten yllä mainitussa kirjassa selitetään, koodin ei pitäisi toimia.
Kommentit
Vastaa
Koodisi näyttää toimivan, koska epäsuorat tyypin muunnokset vahingossa tekevät oikein.
getchar()
palauttaa int
arvon, joka joko sopii alueelle unsigned char
tai on EOF
( jonka on oltava negatiivinen, yleensä se on -1). Huomaa, että EOF
itsessään ei ole merkki, vaan merkki siitä, että merkkejä ei ole enää käytettävissä.
Tallennettaessa tulosta osoitteesta getchar()
kohdassa c
on kaksi mahdollisuutta. Joko tyyppi char
voi edustaa arvoa, jolloin arvo on c
. Tai tyyppi char
ei voi edustaa arvoa. Siinä tapauksessa ei ole määritelty, mitä tapahtuu. Intel-suorittimet pilkkovat vain korkeat bitit, jotka eivät sovi uuteen tyyppiin (pienentäen tehokkaasti moduuli 256 arvoa char
), mutta siihen ei pidä luottaa.
Seuraava vaihe on verrata c
ja EOF
. Kuten EOF
on int
, c
muunnetaan myös int
-asetukseksi säilyttäen tallennettu arvo tiedostossa c
. Jos c
voisi tallentaa arvon EOF
, vertailu onnistuu , mutta jos c
ei pystyisi ei tallentamaan arvoa, vertailu epäonnistuu, koska tietoja on menetetty peruuttamattomasti muunnettaessa EOF
kirjoittamaan char
.
Vaikuttaa siltä, että kääntäjäsi valitsi tyypin char
allekirjoitettu ja arvo EOF
on pieni riittää mahtumaan char
. Jos char
ei ole allekirjoitettu (tai jos olet käyttänyt unsigned char
), testi olisi epäonnistunut, koska unsigned char
ei voi pitää arvoa EOF
.
Huomaa myös, että koodissasi on toinen ongelma. Kuten EOF
ei ole itse merkki, mutta pakotat sen char
-tyyppiin, siellä on todennäköisesti merkki, joka tulkitaan väärin EOF
ja puolet mahdollisista merkeistä ei ole määritelty, käsitelläänkö ne oikein.
Kommentit
- Pakottaminen
char
-arvojen kirjoittamiseksi alueen ulkopuolelleCHAR_MIN
..CHAR_MAX
tulee joko tuottaa joko Toteutuksen määrittelemä arvo, tuottaa bittikuvion, jonka toteutus määrittelee ansan esitykseksi, tai nostaa toteutuksen määrittämän signaalin. käy läpi paljon ylimääräistä työtä tehdäkseen muuta kuin kaksi ' s-komplementin vähennystä.Jos standardikomitean jäsenet hyväksyivät ajatuksen, että kääntäjiä tulisi kannustaa noudattamaan useimpien muiden kääntäjien käytäntöjen mukaista käyttäytymistä, ellei ole syytä toisin tehdä … - … pidän sellaista pakottaminen luotettavaksi (ei tarkoita sitä, että koodin ei pitäisi ' t dokumentoida aikomuksiaan, mutta että
(signed char)x
on pidettävä selkeämpänä ja aivan kuten turvallinen kuin((unsigned char)x ^ CHAR_MAX+1))-(CHAR_MAX+1)
.) Sellaisena kuin se onkin, en näe ', että kääntäjät todennäköisesti toteuttavat muuta käyttäytymistä, joka noudattaa tänään ' s standardi; yksi vaara olisi, että standardia saatettaisiin muuttaa rikkomalla käyttäytyminen oletetun edun mukaisesti " optimoinnissa ". - @supercat: Standardi on kirjoitettu siten, että yksikään kääntäjä ei tarvitse tuottaa koodia, jolla on käyttäytymistä, jota tavallisesti prosessori ei tue. Suurin osa määrittelemättömästä käyttäytymisestä on olemassa, koska (standardin kirjoittamisen aikaan) kaikki prosessorit eivät käyttäytyneet johdonmukaisesti. Kun kääntäjät ovat kypsymässä, kääntäjien kirjoittajat ovat alkaneet hyödyntää määrittelemätöntä käyttäytymistä aggressiivisempien optimointien tekemiseksi.
- Historiallisesti standardin tarkoitus oli pääosin kuten kuvailet, vaikka standardi kuvaa joitain käytäntöjä riittävä yksityiskohta, jotta joiltakin yhteisiltä alustoilta vaaditaan kääntäjiä tuottamaan enemmän koodia kuin mitä löysemmässä määrittelyssä vaaditaan.
int i=129; signed char c=i;
-tyyppinen pakko on yksi tällainen käyttäytyminen. Suhteellisen harvoilla prosessoreilla on käsky, joka tekisic
-arvoksii
, kun se ' s alue -127 – +127 ja tuottaisi kaikkieni
-arvojen johdonmukainen kartoitus arvoihin alueella -128 – +127, jotka poikkesivat kahdesta ' s-komplementin vähennys tai … - … nostaisi jatkuvasti signaalia tällaisissa tapauksissa. Koska standardi edellyttää, että toteutukset joko tuottavat yhdenmukaisen kartoituksen tai tuottavat jatkuvasti signaalin, ainoat alustat, joissa standardi jätä tilaa muulle kuin kahdelle ' s-komplementin pienennys, ovat asioita kuten DSP: t, joissa on kyllästysaritmeettinen laitteisto. Määrittelemättömän käyttäytymisen historiallisesta perustasta sanoisin, että asia ei ole ' vain laitteistoalustoilla. Jopa alustalla, jossa ylivuoto käyttäytyisi hyvin johdonmukaisesti, voi olla hyödyllistä, että kääntäjä ansaitsee sen …
0xff
. Tuloksen tallentaminengetchar()
kohdassaint
ratkaisee ongelman. Kysymyksesi on pohjimmiltaan sama kuin kysymys 12.1 comp.lang.c FAQ: ssä , mikä on erinomainen resurssi. (Lisäksimain()
tulisi ollaint main(void)
, ja se ei sattuisi lisäämään 'return 0;
ennen viimeistä}
.)