Lidi dělají divné věci. Například spouští Linux v Excelu. Využít je emulátor RISC-V mini-rv32ima sestavený jako knihovna DLL, která je volaná z makra VBA (Visual Basic for Applications).
Revolut nabídne neomezený mobilní tarif za 12,50 eur (312 Kč). Aktuálně startuje ve Velké Británii a Německu.
Společnost Amazon miliardáře Jeffa Bezose vypustila na oběžnou dráhu první várku družic svého projektu Kuiper, který má z vesmíru poskytovat vysokorychlostní internetové připojení po celém světě a snažit se konkurovat nyní dominantnímu Starlinku nejbohatšího muže planety Elona Muska.
Poslední aktualizací začal model GPT-4o uživatelům příliš podlézat. OpenAI jej tak vrátila k předchozí verzi.
Google Chrome 136 byl prohlášen za stabilní. Nejnovější stabilní verze 136.0.7103.59 přináší řadu novinek z hlediska uživatelů i vývojářů. Podrobný přehled v poznámkách k vydání. Opraveno bylo 8 bezpečnostních chyb. Vylepšeny byly také nástroje pro vývojáře.
Homebrew (Wikipedie), správce balíčků pro macOS a od verze 2.0.0 také pro Linux, byl vydán ve verzi 4.5.0. Na stránce Homebrew Formulae lze procházet seznamem balíčků. K dispozici jsou také různé statistiky.
Byl vydán Mozilla Firefox 138.0. Přehled novinek v poznámkách k vydání a poznámkách k vydání pro vývojáře. Řešeny jsou rovněž bezpečnostní chyby. Nový Firefox 138 je již k dispozici také na Flathubu a Snapcraftu.
Šestnáctý ročník ne-konference jOpenSpace se koná 3. – 5. října 2025 v Hotelu Antoň v Telči. Pro účast je potřeba vyplnit registrační formulář. Ne-konference neznamená, že se organizátorům nechce připravovat program, ale naopak dává prostor všem pozvaným, aby si program sami složili z toho nejzajímavějšího, čím se v poslední době zabývají nebo co je oslovilo. Obsah, který vytvářejí všichni účastníci, se skládá z desetiminutových
… více »Richard Stallman přednáší ve středu 7. května od 16:30 na Technické univerzitě v Liberci o vlivu technologií na svobodu. Přednáška je určená jak odborné tak laické veřejnosti.
Minule jsem psal, jak jsem vyrostl z C++. Protože jsem asi nějak postižený při programování semestrálky v Javě se mi vybavil jeden krásný C++ hack.
Některé učebnice programovacích jazyků (neplést s učebnicemi programování) mají v některé z úvodních kapitol povídání o r-hodnotách a l-hodnotách. Nebudu to protahovat: r-hodnoty nemůžou stát na levé straně přiřazení, jsou v daném okamžiku jen pro čtení. Typickým příkladem budiž návratová hodnota funkce nebo výsledek aritmetické operace.
double y = sin(x); sin(x) = y; // tohle neprojde, jakkoliv je to logicky správně![]()
V C++ to (jak se na nástroj hackerů sluší) to obecně neplatí. V C++jsou totiž reference. Reference jsou v podstatě ukazatele, které se automaticky dereferencují. Je to bezpečnější, než ukazatel.
char& foo() { static char inner = 'a'; return inner; }
Tato funkce vrací referenci na proměnnou inner
. (Programátoři v C vědí, že proměnná ve jmenném prostoru funce s modifikátorem static je vlastně globální proměnná viditelná jenom uvnitř té funkce. Taky hezká věc.)
No a teď už je návratová hodnota z funkce l-hodnotou
foo() = 'b'; // přiřadí do proměnné inner 'b' cout << foo(); // vytiskne béčko
Čili máme nádherný getter - setter, o kterém se žádnému javistovi ani nesní .
Reference jsou bezpečnější ukazatele. Nejde s nimi dělat pointerová aritmetika. Reference typicky ukazují na nějaký objekt vytvořený staticky na zásobníků, tekže nehrozí "oslepnutí". Samozřejmě Segmentation Fault / Access Violation jde referencí krásně vytvořit, jsme přece v jazyce neomezených možností.*
int *foo = NULL; // tak jestli tenhle pointer není slepý, tak jsem Mikuláš int& ref = *foo; // slepá reference cout << (foo == &ref) << endl; // vypíše 1 adresy jsou stejné ref = 10; // segfault přímo zde, dámy a pánové
Neodpustím si ještě jednu specialitku. Každý, kdo umí C ví, že s polem se v céčku obvykle pracuje přes ukazatel na první prvek. (Kdo si myslí, že pole a ukazatel je v céčku jedno a to samé, ten C neumí.) Přístup do pole jde vyjádřit pointerovou aritmetikou.
char buf[255]; foo[8] == *(foo+8); // toto je vždy TRUE, ekvivalentní zápisy
Ale sčítání je komutativní, klidně by tam mohlo být 8+foo
. Málokdo ví, že lze taky psát:
8[buf] = 'q';
Tedy indexovat číslo polem . Hezké, ne?
* Zájemcům doporučuji nastudovat ukazatele (v originální terminologii "access") v Adě95. Je jich tam několik typů a jsou bezpečné. Ale některá pravidla pro viditelnost jsem tehdá nepobral .
Tiskni
Sdílej:
char& foo() { static char inner = 'a'; return a; }
Má tam být return inner;
foo() = 'b'; // přiřadí do proměnné inner 'b' cout << foo(); // vytiskne béčko Čili máme nádherný getter - setter, o kterém se žádnému javistovi ani nesníTo se od C liší jen ve hvězdičce před foo(), the C++ way by byla třída foo s operátorem=, operátorem<< pro ostream, konverzním operátorem na char a tak dál.
OK, neumím C, jaký je tedy rozdíl mezi polem a ukazatelem?
$ cat array.c #include <stdio.h> void f(char**p) { *p += 1; } int main() { char a[5] = "ahoj"; char *p = a; printf("a (%p): \"%s\"; p (%p): \"%s\"\n", a, a, p, p); f(&p); printf("a (%p): \"%s\"; p (%p): \"%s\"\n", a, a, p, p); f(&a); printf("a (%p): \"%s\"; p (%p): \"%s\"\n", a, a, p, p); return 0; } $ gcc -Wall array.c array.c: In function ‘main’: array.c:17: warning: passing argument 1 of ‘f’ from incompatible pointer type $ ./a.out a (0xbffc1d43): "ahoj"; p (0xbffc1d43): "ahoj" a (0xbffc1d43): "ahoj"; p (0xbffc1d44): "hoj" a (0xbffc1d43): "bhoj"; p (0xbffc1d44): "hoj"
char a[] = "Hello, world!"; char* p; p = a; /* OK */ a = p; /* nelze */ printf("sizeof(p) = %lu\n", sizeof(p)); printf("sizeof(a) = %lu\n", sizeof(a));
char a[] = "abcd"; char* b = "abcd"; a[0] = 'x'; // OK b[0] = 'y'; // viz nížeTohle je velice záludné a nebezpečné, protože to mnohé kompilátory neodhalí, a program někdy běží a jindy padá.
a
je normální pole vytvořené na zásobníku a inicializované příslušným řetězcem. Kdežto b
je ukazatel na konstantní řetězec (mělo by tedy správně být const char* b
). Kompilátory ale většinou dovolí (dokonce bez varování) použít nekonstantní pointer, a problémy se vyrojí až za běhu.
void funkce(char *parametr) { int i; for (i = 0; i < 256; i++) parametr[i] = 0; } void slozitejsi(char *pole[256]) { int i, j; for (i = 0; i < 256; i++) for (j = 0; j < 256; j++) pole[i][j] = 0; } int main() { char prvni_pole[256]; char *druhe_pole = (char *) malloc(256); char *treti_pole[256]; char **ctvrte_pole = (char **) malloc(256*sizeof(char *)); char pate_pole[256][256]; int i; for (i = 0; i < 256; i++) { treti_pole[i] = (char *) malloc(256); ctvrte_pole[i] = (char *) malloc(256); } /* toto se chová stejně */ funkce(prvni_pole); funkce(druhe_pole); /* tohle také */ slozitejsi(treti_pole); slozitejsi(ctvrte_pole); #if 0 /* tohle nejde */ slozitejsi(pate_pole); #endif return 0; }
Pole je uspořádana homogenní n-tice.Což vyžaduje kontrolu mezí, která jak známo v Céčku co? No není :) OK, pár příspěvků v této diskusi mne přesvědčilo o tom, že skutečně nelze zaměňovat pole a ukazatel. Ale na tom, že céčkovské pole není skutečné pole, trvám :)
Uspořádáná homogenní n-tice samozřejmě kontrolu mezí nutně nevyžaduje.Pětice, která mi je ochotna vrátit svůj šestý (nebo nedej bože mínus prvý) prvek podle mne není pětice, nýbrž hodně divný způsob nepřímého přístupu k paměti (ukazatel ;) ).
begin end.
blok. Tato věc mi v C chyběla.
static void __attribute__((constructor)) je_mi_smutno_po_begin_end_bloku() { /* něco si tu udělám */ }Ale není to moc podle normy... V C++ lze dělat i takovéto skopičiny. (Pro zajímavost přikládám celý program, který je inspirován tímto zadáním: http://www.fi.muni.cz/usr/jkucera/pb161/color.htm)
#include <iostream> #include <string> using namespace std; class ColorMap { private: ColorMap(); public: static ColorMap colormap; static const int colorcount; static char colors[]; static int inv_colors[256]; }; const int ColorMap::colorcount = 8; char ColorMap::colors[] = "KRGYBMCW"; int ColorMap::inv_colors[256]; ColorMap ColorMap::colormap; ColorMap::ColorMap() { int i; for (i = 0; i < 256; i++) inv_colors[i] = -1; for (i = 0; i < colorcount; i++) { inv_colors[static_cast<int>(colors[i])] = i; inv_colors[static_cast<int>(colors[i]) + 0x20] = i; } } class color { public: color(const char _color = 'K') : color_int(ColorMap::inv_colors[static_cast<int>(_color)]) { } color(const color& _color) : color_int(_color.color_int) { } color operator+ (const color& c) const { color newcolor(*this); newcolor.color_int |= c.color_int; return newcolor; } color operator* (const color& c) const { color newcolor(*this); newcolor.color_int &= c.color_int; return newcolor; } friend std::ostream& operator<< (std::ostream& s, const color c) { return s << ColorMap::colors[c.color_int]; } friend std::istream& operator>> (std::istream& s, color& c) { char _color; int color_int; while (s >> _color) { if ((color_int = ColorMap::inv_colors[static_cast<int>(_color)]) >= 0) { c.color_int = color_int; break; } cout << "Zadání barvy bylo chybné, zadejte, prosím, jedno z písmen " << ColorMap::colors << ": "; } return s; } int color_int; private: };
Třeba v STL by se pár užitečných příkladů našlo.
No, zas tak hrozné to snad není. Já v tom udělal asi 10k program a šlapalo to, když se člověk vyhnul šablonám. Jak by řekl klasik: Když víš, které konstrukce způsobují interní chybu překladače, můžeš v pohodě programovat.V mém případě tou konstrukcí bylo
if
. A programovat bez if
je velmi obtížné.
V BCB jsem narazil ještě na jedu krásnou chybu. Při debugování se po najetí myší nad proměnnou zobrazí v bublině její hodnota. Problém byl, když ta proměnná byl integer ve tvaru i++ nebo ++i. Pak to nejen zobrazilo hodnotu, ale rovnou to číslo i inkrementovalo. Takže po prvním najetí tam bylo 1, pak 2, 3 atd. Trvalo mi pár hodin, než jsem na to přišelNaštěstí jsem v té době ještě byl zvyklý debugger nepoužívat (jedine pro post-mortem). Bohužel jsem od té doby vyměkl.
Já vím, že se dočkám. Naštěstí existuje Microsoft, který se svým .NET prostředím dokázal to, co jsem si dlouhá léta myslel, že nebude možné. A to probudit Sun ze svého bahýnka sebechvály na Javu a ukázat, že Java má co zlepšovat. Takže jsem se třeba dočkal šablon, autoboxu a věřím, že se dočkám i operátorů.To se snad nikdy nestane. Bohatě stačí již udělané boty. Zvláště autoboxing+autounboxing .
==
. Přesněji to, že je přetížený a má dvě zcela rozdílné funkce: buď porovnává hodnoty (u primitivních typů) nebo reference (u objektů). Typická ukázka, kam vede přetěžování operátorů...
Správně by měly být operátory dva: jeden pro porovnání hodnoty, druhý pro porovnání referencí.
Viz Python a operátory '==' a operátor 'is'. Ale nejlepší řešení je runtime systém který zaručuje že totožné integery nebo totožné stringy mají identické reference, pak není druhý operátor opravdu potřeba.Jistě. Ale to se motáme pořád dokola - že primitivní typy do opravdu objektového jazyka nepatří. Nu, co se dá dělat... Mnohem víc mi ale v Javě chybí metody tříd.
Mnohem víc mi ale v Javě chybí metody tříd.Možná mi něco uniklo, ale mám li třeba třídu:
public class Trida { private final int a = 5; // metoda tridy public static int vratA() { return(this.a); } }Tak potom můžu volat metodu třídy takto:
int moje_a = Trida.vratA()
Tedy alespoň ve všech učebnicích Javy se tomuto volání říká volání metody třídy. Ale možná si měl na mysli něco jiného.
this
sem si nebyl jistej. Ale je pravda, že o metodách třídy i o metodách instance se zmiňuje pan Herout ve své (dle mne docela dobré) knize "Učebnice jazyka Java".
Ale o to jde. Java prostě zvolila špatnou cestu. Dokonce i Microsoft, když tvořil svůj .NET toto podstatně zdokonalil, i když také zůstal na půl cesty. U .NET existuje daleko více primitivních typů, ale všechno je objektem. I int je objektem a třeba konstrukce 123.ToString() je v C# platná. Stejně tak to funguje třeba ve Smalltalku, nebo v jiných, opravdu objektových jazycích.Ale prdlajs. C# převzalo primitivní typy z Javy, jenom tam dali autoboxing/autounboxing hned.. Pravda je, že je to daleko více zaintegrované a programátor o tom ani nemusí vědět... do jisté míry. Více viz například zde Uznávám že se to dá brát jako podstatné zdokonalení.
Pak je pro Javu autoboxing jenom dalším prvkem bordelu, který tam vnesla. Prostě Java se jenom topí v bordelu, který si způsobila tím, že neprohlásila promitivní typy za objekty, což by jí nic nestálo a bylo by to efektivnější řešení.No jo, dneska se to lehko mluví, když to víme... Ale jak jsem již zmínil, asi by to bylo rozhodnutí správné technicky, ale velmi špatné politicky.
V C++ neexistuje problém tohoto typu. V C++ je naprosto jasné z použití operátorů, zda porovnáváte hodnotu, nebo adresu. Operátory == a != v C++ vždycky porovnávají hodnotu.To je nějaký fór? Schválně jsem se podíval, a
==
i !=
by měly být přetížitelné.
Ale je to perfektní ukázka toho, co je na přetěžování operátoru špatného: i když se může zdát že je zcela bezpečné, stejně o něj člověk zakopne a rozbije si hubu. I kdyby to bylo za 10 let.
A co jste taktně ignoroval byla moje poznámka, že v C# neexistují nic než objekty. Tedy neexistuje, že by třeba int nebyl objekt, jako je tomu třeba v Javě.Pokud budeme hodnotové typy považovat za objekty - pak je to ovšem jen otázka terminologie. Nebo pokud přistoupíme na to, že boxing/ungoxing je zcela transparentní (což není). Ani s jedním nesouhlasím. Nelze situaci v C# srovnávat se Smalltalkem, CLOS či dalšími - sice se to tak napůl tváří, ale ne zcela.
No jo, dneska se to lehko mluví, když to víme... Ale jak jsem již zmínil, asi by to bylo rozhodnutí správné technicky, ale velmi špatné politicky. Vědělo se to už tehdy. Už tehdy existovaly objektové jazyky, které měly všechny typy jako objekty. Otázkou je, jak říkáte, co bylo průchodné politicky.Přesně to jsem měl na mysli.
A druhak váš důkaz není nic jiného, než co můžete provést s jakoukoli vlastností programovacího jazyka.Jednak nebyl žádný důkaz, jenom poznámka mimochodem. Druhak jsem jasně napsal, že měly být vytvořeny operátory dva, jak se ukázalo při rozšiřování. Přetěžování operátorů je velmi kontroverzní věc a v podstatě se nedá vyřešit (flamewar není řešení). Každopádně je zcela proti základní filozofii jazyka Java a nepatří tam. Přidáváním takovýchto featur by se z toho stal úplně jiný jazyk.
V javě je dokonce operátor klíčové slovoV Javě jsou (neimplementovaná) klíčová slova goto a const, ale o klíčovém slovu operator slyším prvně. Našel jsem akorát tohle: http://jira.opensymphony.com/browse/WF-281, na java.sun.com ani slovo.
třeba se dočkášDoufám že ne, úplně mi stačí statické importy a auto(un)boxing :) Jsem rád, že Anders Hejlsberg dělá na .NETu a ne na Javě :)
Cynická poznámka: nevzniklo takhle nějak céčko? :-)
#include <iostream> #include "pretizeni.h" using namespace std; main() { int a = 3; int b = 4; cout << (a + b) << endl; return 0; }I když to zní divně, tak vypíše
-1
. Je poněkud vylepšen hlavičkovým souborem pretizeni.h
:
#ifndef __PRETIZENI_H #define __PRETIZENI_H #include <ostream> class INT { public: INT() : hodnota(0) { } INT(int _hodnota) : hodnota(_hodnota) { } friend INT operator+ (INT&, INT&); friend INT operator- (INT&, INT&); friend std::ostream& operator<< (std::ostream&, INT&); friend std::ostream& operator<< (std::ostream&, INT ); private: int hodnota; }; INT operator+ (INT& a, INT& b) { return INT(a.hodnota-b.hodnota); } INT operator- (INT& a, INT& b) { return INT(a.hodnota+b.hodnota); } std::ostream& operator<< (std::ostream &s, INT& a) { return s << a.hodnota; } std::ostream& operator<< (std::ostream &s, INT a) { return s << a.hodnota; } #define int INT #endif
int hodnota
, si můžu inicializovat klidně i vevnitř a normálně, zatímco běžné objekty jdou jen před konstruktorem. Ještě můžu mít tu smůlu, že na sobě nějak závisí. To už pak je rovnou lepší použít ukazatele, new
a delete
.
P.S.: Ve výše uvedeném příkladu jsem ještě jaksi zapomněl v operátoru <<
použít const INT&
, takže jsem jej zavedl dvakrát. To mám z toho ponocování. Přetěžování operátorů je ještě celkem srozumitelné. Skutečné depresi jsem propadl až tehdy, když jsem objevil pointery na metody… :-)
#include <iostream> class T { public: T() {}; void ma(int x) { std::cout << "T::ma(" << x << ")\n"; } void mb(int x) { std::cout << "T::mb(" << x << ")\n"; } }; typedef void (T::*method_pointer)(int); void call(T* x, method_pointer m, int n) { (x->*m)(n); } int main() { T x; call(&x, &T::ma, 1); call(&x, &T::mb, 2); }
class Trida { public: void metoda(void); } instance; void Trida::metoda(void) { printf("To JE ale prasarna!\n"); } void (Trida::*funkce(void))(void) { return Trida::metoda; } void main() { void (Trida::*uk)() = funkce(); (instance.*uk)(); }
const dsql_nod* const* const end:-)
Zkoušeno pod BCB, MSVC, GCC. Možná je to dáno závazným způsobem vyhodnocení té konstrukce, nevím.Chtělo by to nahlédnout to K&R Bible. Jestli zítra (vlastně už dnes...) vzpomenu.