EOF (Dosya Sonu) karakterini karakter türünde saklama


11

Bir değişkenin EOF tutması için kullanılması gereken Dennis Ritchie'nin C Programlama Dili kitabında okudum - intEOF değerini tutabilmesi için yeterince büyük hale getirmek için - değil char. Ancak aşağıdaki kod iyi çalışır:

#include<stdio.h> 

main()  { 
  char c; 
  c=getchar(); 
  while(c!=EOF)  { 
    putchar(c); 
    c=getchar(); 
  } 
} 

Başka girdi olmadığında, getcharEOF değerini döndürür. Ve yukarıdaki programda, cchar türüne sahip değişken , onu başarıyla tutabilir.

Bu neden işe yarıyor? Yukarıda belirtilen kitaptaki açıklamaya göre, kod çalışmamalıdır.



5
Bu kod, değeri olan bir karakteri okursanız başarısız olur 0xff. Sonucunu saklanması getchar()bir in intçözer bu sorunu. Sorunuz , mükemmel bir kaynak olan comp.lang.c SSS bölümündeki soru 12.1 ile aynıdır . (Ayrıca, main()olmalı int main(void)ve bir ekleme bile incitmez return 0;kapanış önce }.)
Keith Thompson

1
@delnan: Bağlantılı makale Unix'in kontrol-D'ye nasıl davrandığı konusunda pek doğru değil. Giriş akışını kapatmaz; yalnızca konsolda engellenen herhangi bir fread () öğesinin henüz okunmamış verilerle hemen dönmesine neden olur. Birçok program fread () işlevinden sıfır baytlık bir dönüşü EOF olarak belirtiyor olarak yorumlar, ancak dosya aslında açık kalır ve daha fazla girdi sağlayabilir.
supercat

Yanıtlar:


11

Kodunuz işe yarıyor gibi görünüyor, çünkü örtük tür dönüşümleri yanlışlıkla doğru şeyi yapıyor.

getchar()veya intaralığına uyan (negatif olması gereken, genellikle -1) bir değere sahip bir değer döndürür . O Not kendisi hiçbir fazla karakter olmadığını belirten bir karakter ama bir sinyal değildir.unsigned charEOFEOF

Sonucunu saklarken getchar()in c, iki olasılık vardır. Her iki tür charde değeri temsil edebilir, bu durumda bu değerdir c. Veya tür değeri temsil char edemez . Bu durumda, ne olacağı tanımlanmamıştır. Intel işlemciler sadece yeni tipe uymayan yüksek bitleri keser (modulo 256 değerini etkili bir şekilde azaltır char), ancak buna güvenmemelisiniz.

Bir sonraki adım karşılaştırmaktır cile EOF. De EOFbir bir int, cbir dönüştürülür intdepolanan değeri muhafaza yanı c. Eğer cdeğerini depolayabilir EOF, daha sonra karşılaştırma başarılı olur, ancak eğer colabilir değil değerini depolamak dönüştürme sırasında bir bilgi onarılmaz kaybı olmamıştır, çünkü, daha sonra karşılaştırma, başarısız olur EOFtürüne char.

Derleyiciniz, chartürü ve EOFsığacak kadar küçük değeri imzalamayı seçti char. Eğer charimzasız edildi (veya kullandığınız olsaydı unsigned char) çünkü test, başarısız olurdu unsigned chardeğerini tutamaz EOF.


Ayrıca kodunuzla ilgili ikinci bir sorun olduğunu unutmayın. EOFBir karakterin kendisi olmadığı gibi , onu bir chartüre zorlarsınız , orada bir varlık olarak yanlış yorumlanan bir karakter vardır EOFve doğru karakterlerin işlenmesi durumunda tanımlanmamış olası karakterlerin yarısı için tanımlanmamıştır.


Yazmak için zorlamak chararalık dışındaki değerler CHAR_MIN.. CHAR_MAX, bir uygulama tanımlı değer elde uygulama bir tuzak temsili olarak tanımlar ya da bir uygulama tanımlı sinyali artırmak bir bit modelini elde için gerekli olmasına olacaktır. Çoğu durumda, uygulamaların ikisinin tamamlayıcı indirgemesinden başka bir şey yapmak için çok fazla işten geçmesi gerekir. Standartlar Komitesi'ndeki insanlar, derleyicilerin aksi takdirde yapılması
gerekmeyen

... böyle bir zorlamayı güvenilir olarak görecektim (kodun niyetlerini belgelememesi gerektiğini söylememeliyim, ama bu (signed char)xdaha net ve aynı derecede güvenli sayılmalıdır ((unsigned char)x ^ CHAR_MAX+1))-(CHAR_MAX+1).) Olduğu gibi, herhangi bir olasılık görmüyorum günümüz standardına uygun diğer davranışları uygulayan derleyiciler; bir tehlike, standardın sözde "optimizasyon" çıkarına yönelik davranışı kırmak için değiştirilebileceğidir.
supercat

@supercat: Standart, hiçbir derleyicinin hedeflediği işlemci tarafından doğal olarak desteklenmeyen davranışları olan kodlar üretmesine gerek kalmayacak şekilde yazılmıştır. Tanımlanmamış davranışların çoğu oradadır çünkü (standardı yazarken) tüm işlemciler tutarlı bir şekilde davranmamıştır. Derleyiciler daha olgunlaştıkça, derleyici yazarları daha agresif optimizasyonlar yapmak için tanımlanmamış davranıştan yararlanmaya başladılar.
Bart van Ingen Schenau

Tarihsel olarak, Standardın amacı çoğunlukla sizin tarif ettiğiniz şekildeydi, ancak Standart bazı ortak platformların daha gevşek bir şartname altında gerekenden daha fazla kod üretmesi için derleyicileri gerektirecek kadar ayrıntılı olarak açıklamaktadır. Zorlama türü int i=129; signed char c=i;böyle bir davranıştır. Nispeten az sayıda işlemcinin -127 ila +127 aralığında olduğu zaman ceşit iolacak ve i-128 ila +127 aralığındaki değerlerin ikisinin tamamlayıcı indirgemesinden farklı olan herhangi bir tutarlı eşlemesini verecek veya ..
supercat

... bu gibi durumlarda sürekli bir sinyal yükseltirdi. Standart, uygulamaların ya tutarlı bir haritalama yapmasını ya da sürekli olarak bir sinyal vermesini gerektirdiğinden, Standardın ikinin tamamlayıcı indirgemesinden başka bir şeye yer bırakacağı tek platformlar, doyurucu-aritmetik donanıma sahip DSP'ler gibi şeyler olacaktır. Tanımsız Davranış'ın tarihsel temeline gelince, sorunun sadece donanım platformlarıyla ilgili olmadığını söyleyebilirim.
Taşmanın
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.