abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
    včera 17:55 | Komunita

    Na čem aktuálně pracují vývojáři GNOME a KDE? Pravidelný přehled novinek v Týden v GNOME a Týden v KDE.

    Ladislav Hagara | Komentářů: 0
    7.6. 14:55 | IT novinky

    Před 70 lety, 7. června 1954, ve věku 41 let, zemřel Alan Turing, britský matematik, logik, kryptoanalytik a zakladatel moderní informatiky.

    Ladislav Hagara | Komentářů: 10
    7.6. 11:44 | Zajímavý software

    NiceGUI umožňuje používat webový prohlížeč jako frontend pro kód v Pythonu. Zdrojové kódy jsou k dispozici na GitHubu pod licencí MIT.

    Ladislav Hagara | Komentářů: 1
    7.6. 10:55 | Nová verze

    Open source platforma Home Assistant (Demo, GitHub, Wikipedie) pro monitorování a řízení inteligentní domácnosti byla vydána ve verzi 2024.6. Z novinek lze vypíchnout lepší integraci LLM (OpenAI, Google AI, Ollama) nebo podporu Matter 1.3.

    Ladislav Hagara | Komentářů: 0
    6.6. 20:55 | IT novinky

    IKEA ve Spojeném království hledá zaměstnance do své nové pobočky. Do pobočky v počítačové hře Roblox. Nástupní mzda je 13,15 liber na hodinu.

    Ladislav Hagara | Komentářů: 0
    6.6. 10:44 | Zajímavý článek

    Alyssa Rosenzweig se v příspěvku na svém blogu Vulkan 1.3 na M1 za 1 měsíc rozepsala o novém Vulkan 1.3 ovladači Honeykrisp pro Apple M1 splňujícím specifikaci Khronosu. Vychází z ovladače NVK pro GPU od Nvidie. V plánu je dále rozchodit DXVK a vkd3d-proton a tím pádem Direct3D, aby na Apple M1 s Asahi Linuxem běžely hry pro Microsoft Windows.

    Ladislav Hagara | Komentářů: 41
    6.6. 01:00 | Nová verze

    Byla vydána (𝕏) květnová aktualizace aneb nová verze 1.90 editoru zdrojových kódů Visual Studio Code (Wikipedie). Přehled novinek i s náhledy a animovanými gify v poznámkách k vydání. Ve verzi 1.90 vyjde také VSCodium, tj. komunitní sestavení Visual Studia Code bez telemetrie a licenčních podmínek Microsoftu.

    Ladislav Hagara | Komentářů: 0
    6.6. 00:44 | Nová verze

    Byla vydána (Mastodon, 𝕏) nová verze 2024.2 linuxové distribuce navržené pro digitální forenzní analýzu a penetrační testování Kali Linux (Wikipedie). Přehled novinek se seznamem nových nástrojů v oficiálním oznámení.

    Ladislav Hagara | Komentářů: 0
    5.6. 16:44 | IT novinky

    Počítačová hra Tetris slaví 40 let. Alexej Pažitnov dokončil první hratelnou verzi 6. června 1984. Mezitím vznikla celá řada variant. Například Peklo nebo Nebe. Loni měl premiéru film Tetris.

    Ladislav Hagara | Komentářů: 10
    5.6. 10:44 | Nová verze

    MicroPython (Wikipedie), tj. implementace Pythonu 3 optimalizovaná pro jednočipové počítače, byl vydán ve verzi 1.23.0. V přehledu novinek je vypíchnuta podpora dynamických USB zařízení nebo nové moduly openamp, tls a vfs.

    Ladislav Hagara | Komentářů: 0
    Rozcestník

    Nepochopitelné chování g++

    4.8.2006 21:31 | Přečteno: 1163× | Linux

    Stále si hraji s programováním Toolkitu. Dnes mě ale docela zarazil překladač g++.

    Mám následující třídy:

    namespace Toolkit{
    
    	template<typename T>
    	class BaseString{
    	protected:
    		typedef T* pT;
    		T *m_pBuffer;
    		unsigned int m_nLength;
    		unsigned int m_nAllocated;
    	public:
    		friend class UnicodeString;
    		BaseString();
    		BaseString( const BaseString& strFrom );
    		BaseString( const T* strFrom );
    		BaseString( const T chrFrom, unsigned int count = 1 );
    		~BaseString();
    		
    		BaseString& operator=( const BaseString& strFrom );
    		BaseString& operator=( const T* strFrom );
    		BaseString& operator=( const T chrFrom );
    		
    		BaseString& operator+=( const BaseString& strFrom );
    		BaseString& operator+=( const T* strFrom );
    		BaseString& operator+=( const T chrFrom );
    		
    		BaseString operator+( const BaseString& str );
    		
    		T& operator[]( unsigned int pos );
    		const T& operator[]( unsigned int pos ) const;
    		
    		operator T*();
    		operator const T*() const;
    		
    		void append( const BaseString& str );
    		void append( const T* str );
    		void append( const T chr, unsigned int count = 1 );
    		
    		unsigned int length() const; // Number of chars !!
    		unsigned int size() const; // Number of bytes
    		void clear();
    	};
    	
    	typedef char AnsiChar;
    	typedef AnsiChar AChar;
    	typedef BaseString<AnsiChar> AnsiString;
    	typedef BaseString<AChar> AString;
    	
    	typedef wchar_t WideChar;
    	typedef WideChar WChar;
    	typedef BaseString<WideChar> WideString;
    	typedef BaseString<WChar> WString;
    	
    	namespace CodePage{
    		enum{
    			cp1250 = 0,
    			cp1251,
    			cp1255,
    			cp437,
    			cp737,
    			cp775,
    			cp850,
    			cp852,
    			cp855,
    			cp857,
    			cp860,
    			cp861,
    			cp862,
    			cp863,
    			cp864,
    			cp865,
    			cp866,
    			cp869,
    			cp874,
    			iso8859_1,
    			iso8859_13,
    			iso8859_14,
    			iso8859_15,
    			iso8859_2,
    			iso8859_3,
    			iso8859_4,
    			iso8859_5,
    			iso8859_6,
    			iso8859_7,
    			iso8859_9,
    			koi8_r,
    			koi8_u,
    			utf8,
    			locale
    		};
    		typedef int CodePage;
    	}
    	
    	class UnicodeString{
    	protected:
    		AnsiString m_sBuffer;
    		unsigned int m_nLength;
    	public:
    		UnicodeString();
    		UnicodeString( const UnicodeString& strFrom );
    		UnicodeString( const WideChar* strFrom );
    		UnicodeString( const WideString& strFrom );
    		UnicodeString( const WideChar chrFrom, unsigned int count = 1 );
    		UnicodeString( const AnsiString& strFrom, CodePage::CodePage codepage = CodePage::locale );
    		
    		UnicodeString& operator=( const UnicodeString& str );
    		UnicodeString& operator=( const WideChar* str );
    		UnicodeString& operator=( const WideString& str );
    		UnicodeString& operator=( const WideChar chr );
    		
    		UnicodeString& operator+=( const UnicodeString& str );
    		UnicodeString& operator+=( const WideString& str );
    		UnicodeString& operator+=( const WideChar* str );
    		UnicodeString& operator+=( const WideChar chr );
    		
    		UnicodeString operator+( const UnicodeString& str );
    		
    		AnsiChar& operator[]( unsigned int pos );
    		const AnsiChar& operator[]( unsigned int pos ) const;
    		
    		operator AnsiChar*();
    		operator const AnsiChar*() const;
    		operator AnsiString() const;
    		operator WideString() const;
    		
    		void append( const UnicodeString& str );
    		void append( const WideChar* str );
    		void append( const WideString& str );
    		void append( const WideChar chr, unsigned int count = 1 );
    		void append( const AnsiString& strFrom, CodePage::CodePage codepage = CodePage::locale );
    		
    		unsigned int length() const; // Number of chars !!
    		unsigned int size() const; // Number of bytes
    		void clear();
    		
    		AnsiString toLocale() const;
    		AnsiString toCodePage( CodePage::CodePage codepage ) const;
    		WideString toWideString() const;
    		
    		static UnicodeString fromLocale( const AnsiString& strFrom );
    		static UnicodeString fromCodePage( const AnsiString& strFrom, CodePage::CodePage codepage = CodePage::locale );
    		static UnicodeString fromWideString( const WideChar* strFrom );
    		static UnicodeString fromWideString( const WideString& strFrom );
    		static UnicodeString fromWideChar( const WideChar chrFrom, unsigned int count = 1 );
    	};
    	typedef UnicodeString UString;
    	
    	
    	typedef UString String;
    	
    }
    
    Pak nastal čas testování, protože vždy se mi něco podaří tak zkonit, že potom padají segfaulty:
    #include <Toolkit/Application.h>
     
    void ToolkitMain()
    {
    	Toolkit::App->init( L"JXP Commander" );
    	
    	Toolkit::UString str1( L"Nějaký řetězec" );
    	Toolkit::UString str2(str1);
    	Toolkit::UString str3( L'=', 80u ); //Problém
    	
    	str1 = str1;
    	str1 += str1;
    	str2 = str1 + str3 + str2;
    	
    	printf("%s\n",(const char*)str2.toLocale());
    	
    	Toolkit::App->run();
    }
    
    Tentokráte jsem to napsal ale napoprvé, bez jediného segfaultu. Problém je ale opět v g++. Ve zdrojáku výše jsem okomentoval řádek, kde je problém. Pokud za tu osmdesátku nepřipíšu to "u", vyhodí mi kompilátor, že tam chce unsigned int. Výborně bych ho chápal, kdyby ovšem na následujícím kódu hodil tu chybu také:
    Toolkit::AString str1( '=', 80 ); //OK
    Toolkit::WString str2( L'=', 80 ); //OK
    

    Další věcí je, že jsem zjistil, že z nějakého mně neznámého důvodu je v linuxu velikost wchar_t rovna 4, kdežto ve windows 2. Jako kdyby těch problému nebylo dost. Pokud bych ale místo wchar_t použil třeba unsigned int, ve Win to proleze, jenže linuxovému g++ zase vadí že L"Bla" je wchar_t*. Takže zatím nechávám wchar_t a v Linuxu bude hold "široký" řetězec zabírat dvojnásobné místo v paměti.

    Ještě bych chtěl jenom dodat, abyste mě nekamenovali za to, že UString nedědí z BaseString, ale že ho obsahuje jako proměnnou. Mám k tomu samozřejmě své důvody. Třeba, že jeden znak v utf8 může být ve skutečnosti znaků více a takto se to lépe ošetřuje.

    Jako poslední věc chci upozornit na změnu licence. Bohužel jsem nucen změnit licenci na GNU/GPL, protože k převodu mezi znakovými sadami jsem použil kód ze siefs modulu pro fuse, který je pod GPL licencován. Bohužel mě to pěkně štve, protože GPL nemám zrovna v lásce. Ještě to ale nevzdávám a poohlédnu se někde jinde. Hlavně trochu prozkoumám glib, protože tam pravděpodobně na nějakou konverzní funkci narazím (zatím vím jen o g_locale_to_utf8 a g_locale_from_utf8).

           

    Hodnocení: 67 %

            špatnédobré        

    Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

    Komentáře

    Vložit další komentář

    Josef Kufner avatar 4.8.2006 21:41 Josef Kufner | skóre: 70
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Odhaduju, že problém je v tom, že gcc neví, který konstruktor z těhle dvou použít.
    UnicodeString( const WideChar chrFrom, unsigned int count = 1 );
    UnicodeString( const AnsiString& strFrom, CodePage::CodePage codepage = CodePage::locale );
    kdežto v BaseString je konstruktor jen jeden
    BaseString( const T chrFrom, unsigned int count = 1 );
    Hello world ! Segmentation fault (core dumped)
    Josef Kufner avatar 4.8.2006 21:42 Josef Kufner | skóre: 70
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    ps: koukal jsem na to asi 20 sec, takže je docela možné, že plácam nesmysly ;-)
    Hello world ! Segmentation fault (core dumped)
    Jardík avatar 4.8.2006 21:53 Jardík | skóre: 40 | blog: jarda_bloguje
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Taky mi něco hlásil. Byly jako "candidates". Ale proč to neví? Přeci AnsiString není ten samý typ jako WideChar a ansi string nemá žádný konstruktor, který by WideChar přebíral.
    Věřím v jednoho Boha.
    Josef Kufner avatar 4.8.2006 22:07 Josef Kufner | skóre: 70
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Jo, ale ty mu nedáš ani jeden, takže neví na co to má přetypovat. Přetypuj to ručně a pojede to. Ale spíš bych ty prototypy upravil tak, aby to bylo jednoznačné, nebo aby byl jen jeden.
    Hello world ! Segmentation fault (core dumped)
    Jardík avatar 4.8.2006 22:40 Jardík | skóre: 40 | blog: jarda_bloguje
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Proč mi hází tohle:
    ./Toolkit/String.h:125: note: candidate 1: Toolkit::UnicodeString::UnicodeString(WideChar, unsigned int)
    ./Toolkit/String.h:126: note: candidate 2: Toolkit::UnicodeString::UnicodeString(const Toolkit::AnsiString&, Toolkit::CodePage::CodePage)
    
    Když tam je jasně v deklaraci i definici const WideChar. L'=' je const wchar_t, takže mu dávám wchar_t. I když změním UnicodeString( const WideChar, unsigned int) na UnicodeString( const wchar_t, unsigned int) stejně nadává. A ještě navíc je ten typedef v namespace Toolkit, proč nenadává s Toolkit::WideChar, když k AnsiString to namespace přidal?
    Věřím v jednoho Boha.
    4.8.2006 22:48 Miloslav Ponkrác | blog: miloslavponkrac
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Neznám souvislosti, takže možná řeknu blbost, ale nedá se wchar_t přetypovat jak na WideChar, tak na AnsiString pomocí jejich konstruktorů?
    4.8.2006 22:53 Michal Kubeček | skóre: 72 | Luštěnice
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Dá - viz níže. Trik je v tom, že se dá implicitně přetypovat na char.
    4.8.2006 22:49 Miloslav Ponkrác | blog: miloslavponkrac
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Neznám souvislosti, takže možná řeknu blbost, ale nedá se wchar_t přetypovat jak na WideChar, tak na AnsiString pomocí jejich konstruktorů?
    Jardík avatar 4.8.2006 22:53 Jardík | skóre: 40 | blog: jarda_bloguje
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Pan Kubeček psal, že se zřejmě snaží wchar_t přetypovat na char. AnsiString má konstruktor, který přebírá char. Hold smůla. Jenom proč tomu tak je.
    Věřím v jednoho Boha.
    4.8.2006 22:44 Michal Kubeček | skóre: 72 | Luštěnice
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++

    Jen na první pohled. Zkuste si přeložit

      Toolkit::AnsiString(L'x');
    

    Překladač to spolkne, protože wchar_t lze implicitně konvertovat na char a poslední konstruktor BaseString umožňuje použít jeden parametr typu char. Je to sice dost krkolomné oproti té konverzi, kterou jste automaticky předpokládal, ale je to korektní. Ta hláška kompilátoru vás upozorňuje, že přestože jedna varianta je horší, podle ISO normy musí překladač považovat obě za přípustné a vyhodit chybu. Nechce se mi teď hledat, jestli to tam skutečně je, ale předpokládám, že autoři gcc se podívali.

    Jardík avatar 4.8.2006 22:51 Jardík | skóre: 40 | blog: jarda_bloguje
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Co se dá dělat? Asi leda nic :-) Zajímavé je, če mingw to vůbec ale vůbec nevadí. Teď budu muset používat "u". No co, mně to ani tak nevadí.
    Věřím v jednoho Boha.
    4.8.2006 23:03 Sinuhet | skóre: 31
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Ve skutecnosti staci dve drobne zmeny:
    namespace CodePage {
            enum CodePage {
    
                    ...
    
            };
            // typedef int CodePage;
    }
    4.8.2006 21:50 Messa | skóre: 39 | blog: Messa
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Nevím co to programuješ, ale jestli hledáš něco pro převod znakových sad, zkusil bych iconv.
    Luk avatar 4.8.2006 21:57 Luk | skóre: 47 | blog: Kacířské myšlenky | Kutná Hora
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    iconv je pod LGPL, takže při dynamickém linkování není problém.
    Šifrování je absolutní nutnost a pomáhá chránit před nekalými živly
    Luk avatar 4.8.2006 21:57 Luk | skóre: 47 | blog: Kacířské myšlenky | Kutná Hora
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Ad licence - pokud mám někde použít cizí kód, tak si dávám velký pozor, aby to nebylo pod GPL/LGPL (LGPL u linkované sdílené knihovny není problém). Pak už to totiž nemohu přímo přelicencovat, i kdybych chtěl - znamenalo by to odstranění toho kódu, což v pozdějších fázích může vyžadovat další zásahy a potenciální problémy. Proto je lepší pro programy, které nejsou (nebo by v budoucnu nemusely být) pod GPL, raději dlouho hledat kód s lepší licencí nebo si to raději znovu implementovat.

    Jinak také varuji před spoléháním na implicitní přetypování (týká se té 80). Může to být zdrojem velice záludných chyb, které se obtížně hledají. Použití správného typu (u konstanty), resp. explicitní přetypování, je v každém případě bezpečnější a zajistí, že má hodnota takový typ, jaký má mít.
    Šifrování je absolutní nutnost a pomáhá chránit před nekalými živly
    4.8.2006 22:45 Sinuhet | skóre: 31
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Mate nejaky specialni duvod pro to, ze jste CodePage nadefinoval jako int a jednotlive jazyky dal do anonymni enumu? A jeste ke vsemu to cele obalil do namespacu?
    4.8.2006 22:52 Michal Kubeček | skóre: 72 | Luštěnice
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Další věcí je, že jsem zjistil, že z nějakého mně neznámého důvodu je v linuxu velikost wchar_t rovna 4, kdežto ve windows 2. Jako kdyby těch problému nebylo dost.

    V čem je problém? Typ wchar_t není zamýšlen pro předávání dat mezi různými platformami, je to typ pro interní reprezentaci Unicode řetězců. Konverzi na přenositelná kódování vám vyřeší automaticky např. operátory << a >> pro zápis do widestreamů a čtení z nich.

    Pokud bych ale místo wchar_t použil třeba unsigned int, ve Win to proleze, jenže linuxovému g++ zase vadí že L"Bla" je wchar_t*. Takže zatím nechávám wchar_t a v Linuxu bude hold "široký" řetězec zabírat dvojnásobné místo v paměti.

    Nechápu, co byste tím chtěl ušetřit. Poslední platforma, na které jsem zažil, že měl int méně než 32 bitů, bylo Borland C++ 4.5, a to ještě jen při v režimu kompilace 16-bitových aplikací pro DOS nebo Windows 3.1.

    Jardík avatar 4.8.2006 22:56 Jardík | skóre: 40 | blog: jarda_bloguje
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Omlouvám se, myslel jsem samozřejmě unsigned short.
    Věřím v jednoho Boha.
    4.8.2006 23:04 Michal Kubeček | skóre: 72 | Luštěnice
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    To bych stejně nepovažoval za dobrý nápad. Za prvé nemáte nikde psáno, že short má 16 bitů, ani že bude na různých platformách stejně velký. Za druhé vám 16-bitový typ nemusí být schopen pojmout všechny potřebné znaky. Že se ve Windows většinou používá UCS-2 a říká se mu UTF-16, to je spíše politováníhodné, rozhodně bych se nesnažil tuto praxi rozšiřovat na další platformy.
    5.8.2006 02:02 Deleted [8409] | skóre: 14 | blog: darkblog
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    tak a je to tady!

    Problém na který jsem narazil a který je těžko řešitelný, protože v linuxu lze udělat následující zápis:
    uint find_char(const wchar_t* s, uint length, wchar_t uc)
    {
      uint i;
      
      for (i = 0; i != length; i++)
      {
        if (s[i] == uc) return i;
      }
      return uint(-1);
    }
    který je ovšem platný ve windows 2000 (používá UCS-2), ale ve windows XP už platný není, protože winxp používá UTF16 a funkce neobsahuje surrogate pair testing (a k čemu by nám vlastně byl, když vstup je wchar_t?).

    Moje řešení znamenalo si napsat svůj string který bude vždy 32 bit. Pokud by autor blogy chtěl, rád pošlu (implementace stringu není hotová za 5 minut a já mám jsem doufám "skoro?" všechny mouchy už chytl). Ke stringu mám hotové i převádění mezi 8 bit formáty a unicode like formáty, vše v licenci BSD. Napsal jsem to pro vlastní toolkit o kterém byla diskuze v minulém blogu.
    Jardík avatar 5.8.2006 12:19 Jardík | skóre: 40 | blog: jarda_bloguje
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Možná teď budu vypadat jako blbec, ale co to je surrogate pair testing? Když tak koukám na ten kód, tak by podle mně měl fungovat všude.
    Věřím v jednoho Boha.
    5.8.2006 13:03 ..... | skóre: 18 | Pardubice
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Znak nad 0xFFFF se v UTF-16 zakóduje pomocí páru znaků, kde první je z rozsahu 0xD800-0xDBFF a druhý z 0xDC00-0xDFFF. Taková dvojice se nazývá surrogate pair. Samotný znak z rozsahu 0xD800-0xDFFF není v Unicode platný.

    Takže pokud je wchar_t 16bitový a řetězce kódované v UTF-16, tak ta funkce nedokáže vyhledat (platné) znaky větší než 0xFFFF a s daným rozhraním ji o to ani nemůžeš požádat. Na vyhledávání platných znaků do 0xFFFF to stačit bude.
    5.8.2006 15:00 Deleted [8409] | skóre: 14 | blog: darkblog
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Tak krásně bych to nenapsal ani já...:-)
    5.8.2006 02:09 Deleted [8409] | skóre: 14 | blog: darkblog
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    zajímalo by mě na které platformě a který kompilér interpretuje short jinak než jako 16 bit int...?

    Jak píšete datové struktury kde chcete 16 bit integer?

    Já osobně si myslím, že:
    • short - 16 bitů, byl a bude
    • int - 32 bitů, sice nebyl, ale je a už asi navždy bude
    • long a void* - 32 nebo 64 bitů
    • long long - 64 bitů vždy
    jestli se mýlím, chci důkaz:-)
    Luk avatar 5.8.2006 02:30 Luk | skóre: 47 | blog: Kacířské myšlenky | Kutná Hora
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    long long - 64 bitů vždy
    To bych netvrdil. Až budou 128-bitové platformy, může být klidně 128 bitů ;-)
    Šifrování je absolutní nutnost a pomáhá chránit před nekalými živly
    5.8.2006 03:03 Michal Kubeček | skóre: 72 | Luštěnice
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Klidně i dříve. Koneckonců, na 32-bitových platformách je tento typ také 64-bitový…
    5.8.2006 03:02 Michal Kubeček | skóre: 72 | Luštěnice
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++

    Svět je mnohem různorodější, než si ho představujete. Stejně jako před pár lety všichni nezodpovědní programátoři brali jako samozřejmost, že long má vždy a všude 32 bitů a vždy také mít bude, berete vy dnes za nezvratitelnou pravdu, že int má a vždy bude mít 32 bitů a long long 64 bitů. Tak tomu ovšem být nemusí a ve svých programech byste na to spoléhat neměl. Jinak budou za pár let na vaši hlavu chrlit sprostá slova ti, kdo je po vás budou muset opravovat, stejně jako já dnes chrlím nadávka na adresu těch, kdo psali a píší své programy s představou, že vždy a všude platí a bude platit sizeof(int) == sizeof(long) == sizeof(void*) == 4.

    Pokud nevěříte, podívejte se do Kernighana a Ritchieho, Appendix A, sekce 2.6, kde jsou uvedeny příklady velikostí datových typů. Je tam mimo jiné uveden počítač Honeywell 6000, na němž má typ short velikost 36 bitů. Jistě, ta kniha už má svá léta, ale na to, že by se nenašla současná platforma s 32-bitovým short, bych si rozhodně nevsadil. Navíc i ISO C99 definuje konstantu CHAR_BITS, o jejíž hodnotě říká pouze to, že má být aspoň 8.

    Jak píšete datové struktury kde chcete 16 bit integer?

    Použiju int16_t a doufám, že to nikdy nikdo (a zejména ne já) nebude muset portovat na platformu, kde tento typ není definován. On totiž podle specifikace definován být nemusí - na platformách, kde žádný 16-bitový celočíselný typ neexistuje. Naštěstí to zase tak často potřeba není - v podstatě jen tehdy, ukládají-li se data do souboru (v binárním formátu) nebo konstruují-li se hlavičky síťových protokolů.

    5.8.2006 04:38 Deleted [8409] | skóre: 14 | blog: darkblog
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    36 bitů je docela mazec, ale je to přes 35 let staré!

    Máte pravdu že představa sizeof(int) == sizeof(long) je špatná, ale myslím si, že sizeof(int) == 4 se v budoucnosti asi měnit nebude, protože int32_t je pouze typedef a pokud by se změnil int na 64 bit, tak by pravděpodobně short byl 32 bit a jak by se udělal int16_t (myslím z čeho, z jakého nativního typu?).

    Na platformě, která nemá 16 bitový typ a kompilér ho neumí prostě máme smůlu a většína 32 a 64 bit platforem chápe short jako 16 bitový typ.

    Pokud budou 128 bit procesory, tak bude long a void* asi 128 bit (i když "zatím" neznám význam tak velké adresy) nebo vznikne nový typ.

    Ale uznávám, že do struktury je opravdu lepší int16_t, i když nevím jestli si ten typedef někdy člověk nebude muset udělat sám:-)
    5.8.2006 04:40 Deleted [8409] | skóre: 14 | blog: darkblog
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Ještě jsem zapoměl dodat, že pokud se jedná o kompatibilitu, tak změna typu char by podle mého názoru znamenala zboření 99% programů.
    5.8.2006 10:41 Michal Kubeček | skóre: 72 | Luštěnice
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Na platformě, která nemá 16 bitový typ a kompilér ho neumí prostě máme smůlu a většína 32 a 64 bit platforem chápe short jako 16 bitový typ.

    Ne, chápe ho tak většina těch, kterým říkám empiričtí programátoři. Tedy ti, které nezajímá nějaká specifikace jazyka a kteří považují program za funkční, pokud jim to chodí. Takoví lidé by zasloužili naplácat přes ruce.

    Pokud budou 128 bit procesory, tak bude long a void* asi 128 bit (i když "zatím" neznám význam tak velké adresy) nebo vznikne nový typ.

    Těžko odhadovat, long asi ano, jestli i void*, to je otázka. Osobně ale zastávám stanovisko, že je to stejně jedno, protože přetypovávání mezi pointery a celočíselnými typy je čuňárna těžkého kalibru. Uvědomte si, že specifikace vám vůbec negarantuje existenci celočíselného typu o stejné velikosti jako pointer - dokážu si docela dobře představit, že by na x86 byl pointer 48-bitová hodnota (16 bitů selektor, 32 bitů offset) a slušně napsané programy by se s tím vypořádaly.

    Ale uznávám, že do struktury je opravdu lepší int16_t, i když nevím jestli si ten typedef někdy člověk nebude muset udělat sám

    Proč struktury? Struktury si vám překladač stejně může v paměti srovnat, jak se mu bude hodit. Jak už jsem napsal, jediné situace, kdy skutečně potřebujete znát velikosti datových typů, je jejich předávání mezi platformami, ať už přes soubor nebo po síti, případně ještě přímá komunikace s hardwarem. Znáte-li nějakou jinou, sem s ní.

    Ještě jsem zapoměl dodat, že pokud se jedná o kompatibilitu, tak změna typu char by podle mého názoru znamenala zboření 99% programů.

    Slušný programátor nebude o typu char předpokládat nic víc, než že má aspoň 8 bitů, (tj. pojme rozsah klasického ASCII plus "horní polovinu tabulky", že jeho velikost odpovídá nejmenší adresovatelné jednotce paměti a že sizeof() vrací hodnoty v násobcích velikosti tohoto typu. Ti ostatní si za své problémy mohou sami. To je totéž jako programátoři, kteří si zjistí, že na jejich platformě je char znaménkový, a na základě toho předpokládají, že je to tak všude.

    5.8.2006 15:16 Deleted [8409] | skóre: 14 | blog: darkblog
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    umíte to krásně napsat, to musím uznat.

    ad long a void) přetypování mezi pointery se dělá docela často a je to někdy nezbytné (to je to samé jak když někdo říká že je hřích goto), abych uvedl příklad už v knihovně C tak se podívejme na funkci sprintf() a myslím že C knihovna není "čuňárna těžkého kalibru".

    ad int16_t) Zarovnávání struktur jde potlačit a někdy to má svůj význam, například když chci šetřit místo (někdy je rozdíl jestli má struktura 1024 bytů nebo 512).

    ad char) Asi jste slušný programátor jenom Vy:-) Řekněte mi že jste nikdy nepočítal s tím, že char má 8 bitů a nebudu Vám věřit.
    Luk avatar 5.8.2006 15:46 Luk | skóre: 47 | blog: Kacířské myšlenky | Kutná Hora
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    to je to samé jak když někdo říká že je hřích goto
    Že je goto hřích se říkalo v dobách, kdy se přecházelo z Basicu a kdekdo cpal goto úplně všude. goto má svůj význam, a např. v linuxovém jádru se vyskytuje celkem hustě.
    Asi jste slušný programátor jenom Vy Řekněte mi že jste nikdy nepočítal s tím, že char má 8 bitů a nebudu Vám věřit.
    Nikdo není dokonalý. Ale spoléhat běžně na to, že něco bude tak či onak, když to není nikde specifikováno (a je to vlastně jen "náhoda", že to tak je), je skutečně cestou do pekel. Od toho existují datové typy s pevnou délkou (int16_t apod.), i když jsou bohužel nepřenositelné.

    Mimochodem existuje ještě mnohem větší čuňárna, kterou člověk také občas vidí, a to nevhodné nakládání s typy, jako je třeba pthread_t. Takže už jsem viděl, že někdo porovnával thready stylem t1 == t2 (kde t1 a t2 jsou typu pthread_t), což je hrubě nekorektní.
    Šifrování je absolutní nutnost a pomáhá chránit před nekalými živly
    6.8.2006 03:35 Deleted [8409] | skóre: 14 | blog: darkblog
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Zajímá mě konkrétně proč je ten pthread_t problém?

    Kdyby to byl jakýkoliv typ tak přece zjištění jestli obsahuje stejnou hodnotu by neměl být problém. Zatím jsem sice neporovnával vlákna, ale na první pokus by mě asi napadla stejná věc, v čem je to nekorektní?

    Jinak goto mám rád také:-)
    Luk avatar 6.8.2006 04:08 Luk | skóre: 47 | blog: Kacířské myšlenky | Kutná Hora
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Problém je to jednak proto, že nikde není řečeno, co ta hodnota typu pthread_t vůbec znamená. V současné linuxové implementaci (NPTL, ale myslím že i LT) je to pointer na strukturu pthread, která se používá uvnitř libpthread. Ovšem může to být obecně cokoliv, třeba nějaká struktura, index v poli, nějaký hash apod. Pro některé datové typy by porovnání nebylo vůbec možné.

    Ale to není to podstatné. Zmíněné porovnávání především není korektní, protože sice bude rovnost hodnot pthread_t znamenat, že se jedná o totéž vlákno, ale obráceně to rozhodně platit nemusí. Mohou být dva různé identifikátory odkazující na totéž vlákno. Pak nebude pro stejné vlákno platit t1 == t2.

    Proto je jedinou korektní cestou pro porovnání vláken volání funkce pthread_equal().
    Šifrování je absolutní nutnost a pomáhá chránit před nekalými živly
    6.8.2006 14:54 Deleted [8409] | skóre: 14 | blog: darkblog
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    díky, pthread_equal() jsem přehlédl:-)
    5.8.2006 15:49 Michal Kubeček | skóre: 72 | Luštěnice
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    přetypování mezi pointery se dělá docela často a je to někdy nezbytné (to je to samé jak když někdo říká že je hřích goto), abych uvedl příklad už v knihovně C tak se podívejme na funkci sprintf()

    Nemluvil jsem o přetypování mezi pointery na různé typy, tomu se v C opravdu nevyhnete. Mluvil jsem o přetypovávání mezi pointery a celočíselnými typy. Tedy když se proměnné typu void* zneužívají k ukládání hodnot typu int nebo long - a nebo naopak. Takové věci jsou bohužel v programech poměrně časté a pro ty, kdo se je snaží portovat na platformy, kde mají tyto typy různou velikost, je to noční můra.

    Zarovnávání struktur jde potlačit a někdy to má svůj význam, například když chci šetřit místo

    Existují platformy, které vás např. nenechají uložit 32-bitové číslo na adresu, která není dělitelná čtyřmi. A nejde o nic exotického nebo dávno zapomenutého. Ruku do ohně bych za to nedal, ale mám pocit, že příkladem je třeba Sparc.

    ad char) Asi jste slušný programátor jenom Vy:-) Řekněte mi že jste nikdy nepočítal s tím, že char má 8 bitů a nebudu Vám věřit.

    Dříve jsem takové věci skutečně z neznalosti dělával. Dnes už o problematice vím víc, takže bych to použil jen v případě opravdu krajní nouze.

    6.8.2006 03:30 Deleted [8409] | skóre: 14 | blog: darkblog
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    já jsem myslel opravdu přetypování mezi ukazatelem a třeba long:
    void* a = 0xdeadbeef;
    printf("%p\n", a);

    Ve funkci vprintf, nebo ještě dál se argument stejně přetypuje na long (nebo typ který velikostně odpovídá pointeru) a pracuje se s ním jako s integerem, třeba unsigned long:-)

    Já programuji hodně dlouho a problém s velikostí char jsem opravdu ještě neměl. Nevím co je krajní nouze, ale myslím že většina knihoven počítá s tím, že char je 8 bit.

    To zarovnání zápisu a čtení na 32 bit o kterém mluvíte opravdu existuje, ale řeší to sám kompilér (ale jestli je to sparc opravdu neřeknu)

    No nic, ještě musím projít nové blogy;-)
    6.8.2006 12:21 Michal Kubeček | skóre: 72 | Luštěnice
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    K tomuhle vás ale vůbec nikdo nenutí.
    6.8.2006 14:55 Deleted [8409] | skóre: 14 | blog: darkblog
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Když mám svoji funkci, která implementuje printf() nebo je jí podobná tak se to řešit musí.
    6.8.2006 15:45 Michal Kubeček | skóre: 72 | Luštěnice
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Možná jsem jen špatně pochopil, co máte na mysli, ale pořád nevidím důvod, proč bych ve variadické funkci musel přetypovávat celočíselný typ na pointer nebo naopak:
    #include <stdio.h>
    #include <stdarg.h>
    
    int args(const char* fmt, ...)
    {
      const char* p;
      va_list ap;
      va_start(ap, fmt);
      for (p=fmt; *p; p++) {
        void* ptr;
        int num;
        switch(*p) {
          case 'p':
            ptr = va_arg(ap, void*);
            printf("%p\n", ptr);
            break;
          case 'i':
            num = va_arg(ap, int);
            printf("%d\n", num);
            break;
          default:
            va_end(ap);
            return -1;
        }
      }
      va_end(ap);
      return 0;
    }
    
    int main()
    {
      int n = 0;
      const char* s = "ahoj";
      if (args("pipi", s, n, &n, 3) < 0)
        return 1;
      return 0;
    }
    
    7.8.2006 01:39 Deleted [8409] | skóre: 14 | blog: darkblog
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Myslím to ještě hlouběji a určitě už víte kam tím mířím.

    Ale zjednodušme si trošku situaci, představme si stream do kterého můžu zapsat hexadecimální hodnotu.

    třeba:
    void writeU64(uint64 value);
    void writeU32(uint32 value);
    void writePtr(const void* value);
    
    Pokud mám vlastní funkce pro převod uint64 a uint32 tak je přece zcela logické že const void* přetypuju podle platformy buď na int32 nebo na int64.

    dělal bych to asi takto:
    inline void writePtr(const void* value)
    {
      if (sizeof(void*) == sizeof(uint64)) {
        writeU64( (uint64)value );
      }
      else if (sizeif(void*) == sizeof(uint32) {
        writeU32( (uint32)value );
      }
      else { 
        ASSERT(1);
      }
    }
    
    Toto je přetypování ukazatele a šlo mi pouze o to, že nazývat to čurárnou mi přijde ujeté, jinak věřím že jste to myslel dobře.
    7.8.2006 11:14 Michal Kubeček | skóre: 72 | Luštěnice
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++

    Ne, pořád nevím, kam tím míříte. Tvrdím, že funkci typu printf() zvládnete bez problémů implementovat, aniž byste musel přetypovávat pointer na celé číslo nebo naopak.

    Já bych to tak nedělal. On tento způsob zápisu binárních hodnot je jednak sám o sobě problematický (kdyby nic jiného, musíte řešit problémy s přenosem mezi big-endian a little-endian platformami), jednak mne nenapadá žádný důvod, proč do streamu ukládat pointer. A i kdybych se k tomu rozhodl, udělám to raději takto:

    const std::ostream& operator <<(std::ostream& s, void* const& p)
    {
      return s.write(&p, sizeof(p));
    }
    

    Jak už jsem upozornil jednou, nemáte absolutně žádnou záruku, že existuje vůbec nějaký celočíselný typ, který má stejnou velikost jako pointer. A stejně tak nemáte žádnou záruku, že existuje celočíselný typ o velikosti právě 32 resp. 64 bitů.

    7.8.2006 15:25 Deleted [8409] | skóre: 14 | blog: darkblog
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Je zajímavé že třeba v BSD C knihovně, nebo GNU C knihovně je to více podobné způsobu který jsem napsal já.

    Endiannes bych musel řešit jen u Vašeho zápisu.
    7.8.2006 15:42 Michal Kubeček | skóre: 72 | Luštěnice
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++

    To je sice možné, ale nic to nemění na skutečnosti, že takový přístup je nevhodný, protože výrazně snižuje přenositelnost projektu. Ostatně, výtky na adresu určitého "vytváření si svého vlastního světa" u (některého) GNU software už jsem viděl mnohokrát…

    Ne, endianness musíte řešit pokaždé, když do streamu (ať už je to soubor nebo síťová komunikace) ukládáte data v binární podobě. Tedy samozřejmě kromě případů, že stoprocentně víte, že veškeré aplikace, která ta data budou sdílet, budou pouze jednoho typu (LE nebo BE). Ale to jsme zase tam, kde jsme byli - u přenositelnosti.

    7.8.2006 22:22 Deleted [8409] | skóre: 14 | blog: darkblog
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Podívejte se pořádně na to co jsem napsal, mám svou funkci, která převede integer na hex string, v tomto případě opravdu nemusím řešit endiannes, protože výstup bude textový a vstup bude v machine endiannes, který na vygenerování textového řetězce nemá vliv.

    V případě Vašem, kde předáváte ukazatel na ukazatel a jeho velikost bych ale tento problém řešit musel, protože už budu převádět na HEX jednotlivé bajty toho čísla.

    Je rozdíl pokud pracuji s int32_t a kde nemusím řešit endiannes nebo pokud pracuji s char a[sizeof(int32_t)].
    8.8.2006 00:10 Michal Kubeček | skóre: 72 | Luštěnice
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Myslím, že nemáte pravdu. Specifikace jazyka vám neříká absolutně nic o tom, jakým způsobem probíhá přetypování pointeru na nějaký celočíselný typ nebo naopak. Opět, jako už mnohokrát předtím, vycházíte pouze ze svých empirických zkušeností z velmi malého vzorku platforem, se kterými se v praxi setkáváte. To je chyba, nechcete-li zbytečně vytvářet nepřenositelné aplikace, nesmíte předpokládat nic, co není zaručeno specifikací jazyka. Navíc jste (několikrát) přehlédl upozornění, že nemáte a priori garantovánu existenci vhodného typu o stejné velikosti jako pointer. A konečně jste stále (přes opakovanou výzvu) neuvedl jediný příklad praktického významu ukládání pointeru do streamu (já opravdu žádný nevidím).
    8.8.2006 14:33 Deleted [8409] | skóre: 14 | blog: darkblog
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    třeba si ho chci vypsat do logu nebo na výstup. Nevím proč to popíráte. V uvedeném příkladu co jsem poslal jsem testoval velikost pointeru a při neúspěšném testu tam byl ASSERT, takže případný porter opraví problém na jedinném místě.
    8.8.2006 15:33 Michal Kubeček | skóre: 72 | Luštěnice
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    V tom případě můžete použít standardní prostředky jazyka, jejichž funkčnost máte zajištěnu specifikací, a není žádný důvod, proč byste měl provádět něco, o čem nemáte nejmenší tušení, jestli to vůbec bude fungovat třeba i po pouhém upgradu knihovny. Spoléhat na to, že něco bude fungovat, jen proto, že jste si to na jedné konkrétní kombinaci platformy a překladače vyzkoušel, je velmi nezodpovědný přístup a za označením čuňárna pro takové programovací techniky si plně stojím.
    8.8.2006 19:59 Deleted [8409] | skóre: 14 | blog: darkblog
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Jestli mi prostředky standardní C knihovny nevyhovují, musím si napsat svoje. To co jsem napsal je naprosto korektní a za tím si stojím zase já!
    8.8.2006 20:46 Michal Kubeček | skóre: 72 | Luštěnice
    Rozbalit Rozbalit vše Re: Nepochopitelné chování g++
    Stát si za tím sice můžete, ale specifikace jazyka říká něco úplně jiného…

    Založit nové vláknoNahoru

    ISSN 1214-1267   www.czech-server.cz
    © 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.