Skip to content
Tiantan
Articles

Lagring av EOF (End of File) -tecken i en char-typ

On februari 18, 2021 by admin

Jag läste i Dennis Ritchies The C Programming Language bok att int måste användas för att en variabel ska hålla EOF – för att göra den tillräckligt stor så att den kan hålla EOF-värdet – inte char. Men följande kod fungerar bra:

#include<stdio.h> main() { char c; c=getchar(); while(c!=EOF) { putchar(c); c=getchar(); } } 

När det finns är inte mer ingång, getchar returnerar EOF. Och i ovanstående program kan variabeln c, med char-typ, hålla den framgångsrikt.

Varför fungerar det? Enligt förklaringen i boken ovan ska koden inte fungera.

Kommentarer

  • Det finns inget EOF-tecken.
  • Den här koden kommer sannolikt att misslyckas om du läser ett tecken med värdet 0xff. Lagrar resultatet av getchar() i en int löser problemet. Din fråga är i stort sett densamma som fråga 12.1 i comp.lang.c FAQ , vilket är en utmärkt resurs. (main() borde också vara int main(void), och det skulle ' inte skada att lägga till en return 0; före den avslutande }.)
  • @delnan: Den länkade artikeln är inte ' inte helt rätt om hur Unix behandlar kontroll-D. Det ' t stänger ingångsströmmen; det orsakar bara att fread () som blockerar konsolen återgår omedelbart med ännu olästa data. Många program tolkar en nollbyte-retur från fread () som indikerar EOF, men filen förblir faktiskt öppen och kan ge mer input.

Svar

Din kod verkar fungera, eftersom de implicita typkonverteringarna av misstag råkar göra rätt.

getchar() returnerar ett int med ett värde som antingen passar intervallet unsigned char eller är EOF ( som måste vara negativ, vanligtvis är det -1). Observera att EOF i sig inte är ett tecken utan en signal om att det inte finns fler tecken tillgängliga.

När du lagrar resultatet från getchar() i c finns det två möjligheter. Antingen typen char kan representera värdet, i vilket fall det är värdet för c. Eller typen char kan inte representera värdet. I så fall är det inte definierat vad som kommer att hända. Intel-processorer hugger bara av de höga bitarna som inte passar in i den nya typen (effektivt minskar värdet modulo 256 för char), men du borde inte lita på det.

Nästa steg är att jämföra c med EOF. Eftersom EOF är en int, c kommer att konverteras till en int, vilket också sparar det lagrade värdet i c. Om c kunde lagra värdet på EOF, kommer jämförelsen att lyckas , men om c inte kunde lagra värdet, kommer jämförelsen att misslyckas, eftersom det har skett en oåterkallelig förlust av information när du konverterar EOF för att skriva char.

Det verkar som att din kompilator valde att göra char -typ signerad och värdet på EOF litet tillräckligt för att passa in i char. Om char inte var signerade (eller om du hade använt unsigned char) skulle ditt test ha misslyckats, eftersom unsigned char kan inte hålla värdet på EOF.


Observera också att det finns ett andra problem med din kod. Som EOF är inte en karaktär i sig, men du tvingar den till en char -typ, det finns mycket troligt en karaktär där ute som tolkas felaktigt som EOF och för hälften av de möjliga tecknen är det odefinierat om de kommer att bearbetas korrekt.

Kommentarer

  • Tvingande för att skriva char värden utanför intervallet CHAR_MIN .. CHAR_MAX krävs krävs för att antingen ge ett Implementationsdefinierat värde, ge ett bitmönster som implementeringen definierar som en fällrepresentation, eller höja en implementeringsdefinierad signal. I de flesta fall måste implementeringar gå igenom mycket extra arbete för att göra något annat än två ' s-komplementreduktion.Om personer i standardkommittén prenumererar på idén att kompilatorer ska uppmuntras att genomföra beteenden som överensstämmer med de flesta andra kompilatorers i avsaknad av skäl att göra annat …
  • … tvång som tillförlitlig (för att inte säga att koden inte ska ' t dokumentera sina avsikter, men att (signed char)x är bör betraktas tydligare och precis som säkert som ((unsigned char)x ^ CHAR_MAX+1))-(CHAR_MAX+1).) Som det är, ser jag ' inte sannolikheten för att kompilatorer implementerar något annat beteende som följer idag ' s standard; den enda faran skulle vara att standarden kan ändras för att bryta beteendet i det förmodade intresset för " optimering ".
  • @supercat: Standarden är skriven så att ingen kompilator behöver producera kod som har beteende som inte naturligt stöds av processorn den riktar sig till. Det mesta av det odefinierade beteendet finns eftersom (vid skrivandet av standarden) inte alla processorer uppförde sig konsekvent. Med att kompilatorerna blir mogenare har kompilatorförfattare börjat utnyttja det odefinierade beteendet för att göra mer aggressiva optimeringar.
  • Historiskt var standardens avsikt mestadels som du beskriver, även om standarden beskriver vissa beteenden i tillräcklig detalj för att kräva kompilatorer för vissa vanliga plattformar för att generera mer kod än vad som skulle krävas enligt en lösare specifikation. Typen tvång i int i=129; signed char c=i; är ett sådant beteende. Relativt få processorer har en instruktion som skulle göra c lika i när det ' är i intervallet -127 till +127 och skulle ge någon konsekvent mappning av andra värden på i till värden i intervallet -128 till +127 som skilde sig från två ' s-komplementreduktion, eller …
  • … skulle konsekvent höja en signal i sådana fall. Eftersom standarden kräver att implementeringar antingen ger en konsekvent mappning eller konsekvent höjer en signal, skulle de enda plattformarna där standarden skulle ge utrymme för något annat än två ' s-komplementreduktion vara saker som DSP med mättande aritmetisk hårdvara. När det gäller den historiska grunden för odefinierat beteende skulle jag säga att frågan inte bara är ' med hårdvaruplattformar. Även på en plattform där överflöd skulle bete sig på ett mycket konsekvent sätt kan det vara användbart att ha en kompilator som fäller den …

Written by admin

Lämna ett svar Avbryt svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *

Senaste inläggen

  • Med hjälp av en balun med en resonansdipol
  • Vad är skillnaden mellan “ kan inte ” och “ kan inte ”? [duplicera]
  • På JFK, kan du flytta mellan terminalerna på sidan om inrikesflyg?
  • “ Uppskattat djupt ” eller “ uppskattade ”
  • Vad betyder ' abstrakta idéer '? [stängd]

Arkiv

  • februari 2021
  • januari 2021
  • december 2020
  • november 2020
  • Deutsch
  • Nederlands
  • Svenska
  • Norsk
  • Dansk
  • Español
  • Français
  • Português
  • Italiano
  • Română
  • Polski
  • Čeština
  • Magyar
  • Suomi
  • 日本語
  • 한국어

Copyright Tiantan 2021 | Theme by Theme in Progress | Proudly powered by WordPress

Back to top