Jak vlastně funguje primitivní datový typ ?   zodpovězená otázka

C#

Dobrý den,

má otázka bude velice prostá a snad zkušené programátory neurazí.

int cislo = 5;

Jak to, že to mohu takhle napsat? Pokud si vytvořím třídu nebo strukturu, tak mi stejně nezbývá nic jiného, než založit její instanci (pokud není statická) a pak až s ní mohu pracovat.

Struktury, pokud se nepletu, dokonce ani statické obvykle nebývají, nebo dokonce být nemohou.

Tak jak to, že to mohu "jen tak" napsat ? ... nepotrebuji new... nepotrebuji nic

int cislo = 5;

... int se tváří jako "všudezdejší", že pro jeho používání není potřeba nic dělat a vše bude fungovat... ale jak to ?

Čemu konkrétně přiděluji těch 5 a co uchovává jejich hodnotu ? datová složka ? property ? ... nemusím ani znát jak se jmenuje a nemusím ani říkat kam chci 5 uložit.

A samotná proměnná cislo je co ? instance ?

Děkuji za případnou odpověd... blbost, ale jakého to dokáže vytvořit v hlavě brouka :)

Pavel Franta

nahlásit spamnahlásit spam 0 odpovědětodpovědět

... ted se nesmejte

Jedina varianta co si predstavuji je ta. Ze instance, např Int32, je treba jiz davno vytvorena, respektive, že kompilátor, dopředu počítá s tím, že bude při sestavení vytvořena a tak mě už předem nechává psát kod, jako kdyby instance již byla vytvořena.

(kdyby to byla uplná blbost, tak si vzpomenme, ze presne takhle vznikají legendární "bulharské" konstanty :D

nahlásit spamnahlásit spam 0 odpovědětodpovědět

.NET ma primitivni datove typy, z nich se sklada defakto vsechno. Pokud vytvorim promennou primitivního typu, tak v paměti je uložena přímo ta HODNOTA

takze u:

int a = 5;

je v pameti primo cislo 5.

v paměti to tedy vypadá takto:

adresa velikost hodnota

.......

.......

.......

0x..... 8B (64bit system) a 5

.......

Pokud však máte neprimitivní datový typ, tak ve skutecnosti

Trida a;

je v pameti reprezentovaná jako odkaz na neco..

adresa velikost hodnota

.......

.......

.......

0x..... 8B (64bit system) a 0x00000(adresa)

.......

Takze pokud napisete pouze Trida a, vytvorite v pameti pouze odkaz (ktery je zatim null 0x000..)

az v okamziku, kdy vytvorite instanci, se na HEAPU vytvori objekt (zabere se pamet a do nej se nasetují membery) a do vašeho Trida a (do odkazu) se nastaví adresa toho objektu na heapu.

Stack:

adresa velikost hodnota

.......

.......

.......

0x..... 8B (64bit system) a 0x112233(adresa)

.......

Heap:

adresa velikost hodnota

.......

.......

.......

0x112233 velikost celeho objektu

0x....koncova adresa - kde konci objekt (jeho membery)

.......

Tento popis je zjednoduseny, jde o to, ze zatimco u primitivnich typu je na dane adrese primo hodnota, tak u referencnich je tam pouze adresa (vedouci nejcasteji na Heap), kde se nachazi instance objektu.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Dobrý den,

děkuji za odpoveď... Pokud se mi snažíte popsat principy že hodnotové typy ukládají do stacku, zatímco referenční ukládají do stacku referenci, která odkazuje na heap. Tam mé vědomosti sahají.

Jde mi spíše o ten zápis.

Jak to, že mohu využívat strukturu s aliasem "int" a nemusím u ní vytvářet žádnou instanci. Mohu používat všechny její metody. Mohu dělat vše jako kdyby byla statická, ale struktury, mám za to, být statické nemohou.

Pořád tedy zůstává otázkou, proč je akceptovatelné toto:

int a = 5;

A ne napriklad toto:

int a = new int(5);

(v realu to nejde, protože Int32 na to nema konstruktor)... obecne se to cele chova totiž, jako když tam můžu sypat co chci a ono si to vygeneruje vlastní příkazy, které budou vypadat jako volání konstruktorů.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Doporučil bych vám knížku illustrated C#, tam to máte vysvětleno i s obrázky a snad pochopíte, proč to tak je - přijde mi, že nechcete uznat rozdíl mezi hodnotovým a referenčním typem.

Věnujte pozornost kapitole Proměnné (Variables) a jejich deklaraci. Zjevně vás trápí inicializace a její zápis je jiný pro value a reference typy. inicializace proměnné typu int prostě proběhne prostým přiřazením, ostatně reference typ to umožňuje také:

SomeClass someClass = null;

(a nebo SomeClass someClass;)

Tím si alokujete paměť na uložení reference (v části paměti nazvané stack) - ale nic použitelného v ní ještě není. A aby tam bylo, musíte si alokovat paměť pro objekt a to se děje pomocí klíčového slova new a paměť je alokována v jiné části nazvané heap. Následně je reference na tuto paměť vložena do již alokované paměti na referenci (stack).

Pro primitivní datové typy není třeba na heapu nic alokovat, tedy klíčové slovo new nelze použít a místo reference se přímo ukládá hodnota, to je ten důvod proč můžete napsat

int a = 5;

Porovnejte si to třeba s:

SomeClass someClass1 = new SomeClass();

SomeClass someClass2 = someClass1;

(nepřipomíná vám to int = 5; ? v principu se děje něco velmi podobného :-), alokuje se paměť na referenci a ta už je známa (objekt na heapu je vytvořen), paměť je tedy rovnou zaplněna konkrétní hodnotou stejně jako u int a = 5)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Dobrý den pane Strimpfle,

moc děkuji za čas, který jste vložil do odpovědi, Vaše odpověď je perfektní :)

Pavel F.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Já bych ještě k tomuto tématu doporučil tento článek:

https://blogs.msdn.microsoft.com/ericlip...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Jeste dodam, ze o všech věcech v paměti, které nejsou dynamicky alokované (+-není u nich new), tedy například:

int a;

Trida a; // JEN ODKAZ, ne instance

struct Bod a;

compiler opravdu předem ví, tudíž vygeneruje takový byte code, který při vytváření rámce funkce / případně instance objectu počítá s tím, že musí na stacku (lokální proměnné) / heapu(instance) nechat místo.

Takže "že instance, např Int32, je treba jiz davno vytvorena, respektive, že kompilátor, dopředu počítá s tím, " je správná myšlenka.. Ví co tam bude, takže na to nechává míst. Jen poupravím, že u primitivních typů neříkáme instance (instance je 1kus nějaké třídy, atp.) u primitivních typů je to prostě 1 "int".

Ještě dodám jednu mírně advanced věc.

V .NETu jsou primitivní typy jako int, float, char atp., jelikož ale autoři chtěli umožnit, aby jste mohl používat tyto primitivní typy i například u kolekcí (List<>), které jsou schopny "pojmout" jen něco co dědí od Object - musí být i tyto primitivní typy tzv. "zapouzdřeny" v nějakém objectu.. tomudle se říká "boxing primitivních typů" a proto jsou tam třídy jako Integer, Float atp..

pokud tedy chcete mít List<int>, tak se při vložení intu do této kolekce "natajnačku" dělá nová instance typu Integer temp = new Integer(a);

a pak se přidá do toho listu.

Tomuto se dá pak předejít, ale to už je na jinou debatu :-)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

To s tím List<int> není pravda, tam se boxing/unboxing nedělá.

Boxing se provede např. pokud máme

object x = 5;

nebo

var list = new ArrayList();
list.Add(5);

tj. když se s hodnotou hodnotového typu potřebuje pracovat jako datový typ object.

Ale generický list je interně implementovan jako pole, které se akorát když dojde volná kapacita vždy alokuje dvojnásobně velké a zkopíruje se ho něj původní data, tj. u List<int> jsou hodnoty držené v int[]. A když se alokuje pole s hodnotovým typem, tak se samozřejmě ví jak je každý prvek velký a prvky jsou ukládané přímo do pole (které je jako jeden objekt na heapu), ne jako boxované hodnoty.

Tak blbě s boxingem/unboxingem to právě dělali staré negenererické kolekce z C# 1.0 jako ArrayList a to byl jeden z hlavních důvodů (samozřejmě spolu s typovou bezpečností) proč byly do C# 2.0 hned přidané generics a vznikly generické kolekce.

viz např. zde:

http://stackoverflow.com/questions/44030...

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Máte pravdu, nevím proč jsem použil zrovna generický list, přesto že vím o tom jak je implementován :-) Asi jsem přepracovaný, vždy jsem to ukazoval na Arraylistu, jako vy.

Děkuji.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback