Bir bilgisayar '\ 0' (boş karakter) 'imzasız int = 0' dan nasıl ayırt eder?


29

Belirli bir durumda, bir dizi karaktere sahipseniz (boş karakterle tabiki biterse) ve bundan hemen sonra, bellekteki bir sonraki pozisyonda, 0imzasız bir int olarak depolamak istiyorsanız , bilgisayar bunlar arasında nasıl farklılaşır? iki?


18
Cevapların tamamen doğru olduğu tipik bilgisayarlar hakkında sorular soruyorsunuz. Ancak, veri türlerini ayırt etmek için etiketli belleği kullanan bazı mimarlar vardı .
Grawity

12
Bilgisayar aynı şekilde 4 baytlık bir float'ı 4 baytlık bir tamsayıdan ayırt edemez (çok farklı bir sayıyı temsil eder).
Hagen von Eitzen

6
Bir dizgiyi 0x00 ile sonlandırmak yaygın olsa da, uzunluk öneki dizeleri kullanan diller vardır. İlk bayt veya iki, dizedeki bayt sayısını içerecektir. Bu şekilde, sonunda bir 0x00 gerekli değildir. Pascal ve BASIC'in bunu yaptığını hatırlıyor gibiyim. Belki de COBOL de.
yandı

@ lit, ayrıca birçok iletişim protokolünde başlık formatları. "Merhaba ben bu tür bir mesajım ve bu kadar uzun baytım". Genellikle, içinde karmaşık veri türlerini saklamanız gerektiğinden, boş sonlandırma ayrıştırmak için çok daha fazla sorun yaratır.
mathreadler

1
@lit: Çoğu Pascal ve BASIC evet ve PL / I ve Ada varyantları - ve alt dize paylaşım 7u6 düştü beri Java etkin bir dizi uzunluk öneki kullanır - ama COBOL sadece sıralama-: yapabilirsiniz okumak verileri pic X occurs m to n depending on v( ve sayım hemen önce değil, her yerde olabilir), ancak saklamak daha karmaşıktır.
dave_thompson_085

Yanıtlar:


86

Öyle değil.

String terminator, 0 bitin tümünü içeren bir bayttır.

İmzasız int, her biri 0 bit içeren (ortamınıza bağlı olarak) iki veya dört bayttır.

İki öğe farklı adreslerde saklanır. Derlenmiş kodunuz, eski konumdaki dizgilere uygun işlemleri ve ikincisindeki işaretsiz ikili sayılar için uygun işlemleri gerçekleştirir. (Kodunuzda bir hata veya tehlikeli bir şekilde akıllıca bir kod yoksa!)

Ancak bu baytların tümü CPU ile aynı görünüyor. Bellekteki veriler (şu anda yaygın olan komut kümesi mimarilerinde), onunla ilişkili hiçbir tür içermiyor. Bu sadece kaynak kodunda var olan ve sadece derleyici için bir anlam ifade eden bir soyutlamadır.

Düzenleme eklendi: Örnek olarak: Bir dizgiyi oluşturan baytlarda aritmetik işlem yapmak, yaygın olarak bile mümkündür. 8 bitlik ASCII karakterlerinden oluşan bir dizginiz varsa, 32 (ondalık) ekleyerek veya çıkararak dizedeki harfleri büyük ve küçük harf arasında dönüştürebilirsiniz. Veya başka bir karakter koduna çeviri yapıyorsanız, değerlerini diğer kodda eşdeğer bit kodlaması sağlayan bir diziye indeks olarak kullanabilirsiniz.

CPU için karakterler gerçekten çok kısa tamsayılardır. (her biri 16, 32 veya 64 yerine sekiz bit.) Bizim için değerlerinin, okunabilir karakterlerle ilişkili olduğu ortaya çıkıyor, ancak CPU'nun bu konuda hiçbir fikri yok. Aynı zamanda, "boş bayt" dizgesinin sona ermesiyle "" C "konvansiyonu hakkında hiçbir şey bilmiyor (ya da diğer cevaplarda ve yorumlarda belirtildiği gibi, bu sözleşmenin hiç kullanılmadığı programlama ortamları var) .

Emin olmak gerekirse, x86 / x64'te, örneğin REP öneki - dizeleriyle çokça kullanma eğilimi olan bazı talimatlar vardır, ancak istenen sonucu elde ederlerse, bunları bir tam sayı dizisinde de kullanabilirsiniz.


14
Bu nedenle geliştiricilerin dizelere dikkat etmesi gerekiyor. Art arda 100 bayt varsa, burada en fazla 99 1 bayt karaktere ve son bayttaki sonlandırıcıya sığdırabilirsiniz. Buraya 100 baytlık bir dize yazarsanız, program dize orada bittiğini anlamayacak ve tesadüf bir sıfır bayta kadar ardışık bayt okumaya devam edecektir. Dize 100 bayttan uzunsa, bazı bitişik verilerin üzerine yazacaktır. Yüksek seviyeli programlama dilleri (Java, C #, JS vb.) Bununla ilgilenir, ancak C, C ++ gibi düşük seviyeli dillerinde meclisin sorumluluğu dev olur.
gronostaj

18
@gronostaj Yorumunuz biraz kafa karıştırıcı: C'den farklı olarak, C ++ karakterleri de bununla otomatik olarak ilgileniyor. C ++ ayrıca genellikle düşük seviyeli bir dil olarak sınıflandırılmaz (ve bazen C bile değildir).
Konrad Rudolph

5
Veri değerlerinde tip işaretleyicileri olan (eski) CPU mimarileri vardır, bu nedenle bir tamsayı işaretçi olarak ayırmak bir istisna verir.
Simon Richter

8
@JamieHanrahan IA64 işlemcisinde , bir değer ayarlanmışsa, bir istisna atabilecek NaT (veya "Bir Şey Yok") adlı bir bit bulunur .
ErikF

4
@KonradRudolph "otomatik", kesinlikle C ++ değil "kusursuz" anlamına gelmez
rackandboneman

5

Kısacası, hiçbir fark yoktur (int'nin 2 veya 4 bayt genişliğinde ve bir karakterin sadece 1 olması dışında).

Mesele şu ki, tüm modern kütüphaneciler ya boş sonlandırıcı tekniğini kullanıyor ya da bir ipin uzunluğunu saklıyor. Ve her iki durumda da program / bilgisayar boş bir karakter okuduğunda dizenin sonuna ulaştığını veya boyutun söylediği kadar karakter okuduğunu bilir.

Boş sonlandırıcı eksik olduğunda veya uzunluk yanlışsa, program başlangıçta olması gereken bellekten okumaya başlar.


3
Oh, kısacası bir fark var - aslında, kısa çok makineye bağlı bir veri türü olması nedeniyle biraz
ünlüydü

2

Arada fark yok. Makine kodu (assembler) değişken tiplere sahip değildir, bunun yerine verilerin tipi talimat ile belirlenir.

Daha iyi bir örnek olabilir intve floateğer bellekte 4 bayt varsa, bunun bir intveya bir float(veya tamamen başka bir şey) olup olmadığına dair hiçbir bilgi yoktur , ancak tamsayı eklenmesi ve yüzdürme eklemesi için 2 farklı komut vardır, yani talimat veri üzerinde kullanılır, sonra bir tamsayıdır ve bunun tersi de geçerlidir.

Dizelerle aynı, örneğin bir adrese bakan ve bir bayta ulaşana kadar bayt sayan bir kod varsa \0, onu bir işlev hesaplama dizesinin uzunluğu olarak düşünebilirsiniz.

Elbette böyle bir programlama tam bir delilik olurdu, bu yüzden makine kodunu derleyen daha yüksek seviyeli dillere ve doğrudan montajcıdaki neredeyse hiç öğlen programlarına sahip olmayız.


2

Tek kelimeli bilimsel cevap şöyle olacaktır: meta veri.

Meta veriler, bilgisayara belirli bir konumdaki bazı verilerin int, dize, program kodu veya her türlü olup olmadığını bildirir. Bu meta veriler Kodun bir parçası olabilir (Jamie Hanrahan'ın bahsettiği gibi) veya açıkça bir yere depolanabilir.

Modern CPU'lar genellikle program koduna atanmış bellek bölgeleri ile veri bölgeleri arasında ayrım yapabilir (örneğin, NX Bit https://en.wikipedia.org/wiki/NX_bit ). Bazı egzotik donanımlar da karakterleri ve sayıları birbirinden ayırabilir, evet. Ancak genel durum, Yazılım'ın bu konuyla ilgilenmesidir (örtük meta verilerde (kodda) veya açık meta verilerde (nesne yönelimli VM'ler) genellikle meta verileri (tür / sınıf bilgileri) verinin bir parçası olarak depolar) (nesne) .

Farklı veri türlerini ayırt etmemenin bir avantajı, bazı işlemlerin çok basit hale gelmesidir. G / Ç alt sisteminin mutlaka okuduğu veya diske yazdığı verilerin aslında program kodu, insan tarafından okunabilen metin veya sayı olup olmadığını bilmesi gerekmez. Hepsi sadece makinenin içinde taşınan parçalar. Program kodunun şık yazma sorunları ile ilgilenmesine izin verin.


0

Öyle değil. Sen yap!

Veya derleyici / tercümanınız.

Talimatlar bilgisayara 0numarayı bir sayı olarak eklemesini söylerse , bunu yapar. Bilgisayara 0, ' \0'char ' olarak ulaştıktan sonra verileri yazdırmayı durdurmalarını söylerlerse , bunu yapar.

Dillerin verilerin nasıl ele alınacağını sağlayacak mekanizmaları vardır. C değişkenler türleri gibi olması int, floatve charve derleyici her veri tipine doğru talimatları üretir. Fakat C, bir değişkenden farklı tipte başka bir değişkene veri aktarmanıza izin verir, sayı olarak kullanılabilecek bir işaretçi bile. Bilgisayara göre hepsi gibi bit.


0

Boş bir karakter bir bayttır ve işaretsiz bir int iki bayttır.

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.