C/C++ & Visual C++

Otßzky a odpov∞di

┌vodem  |  DatovΘ struktury |  Kurz DirectX  |  Downloads  |  Otßzky a odpov∞di

 

V tΘto Φßsti budou zve°ejn∞ny vaÜe dotazy i s naÜφ odpov∞dφ. Tak si budou moci odpov∞∩ p°eΦφst vÜichni zßjemci a ne pouze tazatel. Dotazy ke Kurzu C/C++ posφlejte na email mΘho kolegy: mrandrew@atlas.cz a dotazy ke kurzu o DirectX posφlejte na m∙j email: jiri.formanek@centrum.cz.

Pro v∞tÜφ p°ehlednost jsem rozd∞lil tuto sekci do vφce Φßstφ:

ObecnΘ otßzky
Dotazy k C++
Dotazy k DirectX
KrßtkΘ p°φklady


ObecnΘ otßzky t²kajφcφ se programovßnφ

Je lepÜφ Microsoft Visual C++ nebo Borland C++?
Osobn∞ bych Vßm doporuΦoval Visual C++, ale je to takΘ v∞c vkusu. Pokud nemßte nic proti Microsoftu tak jd∞te do Visual C++, v opaΦnΘm p°φpad∞ do Borlandu, kter² sice nenφ Üpatn², ale podle mΘho nßzoru se VC++ nevyrovnß. Microsoft mß urΦit∞ lepÜφ podporu nebo spφÜ reklamu:)

Lze zm∞nit nastavenφ ji₧ rozpracovanΘho projektu na statickΘ linkovanφ MFC, ani₧ bych musel projekt znovu zavßd∞t?
Samoz°ejm∞. V menu Project zvolte polo₧ku Settings. Tam hned na prvnφ kart∞ najdete zp∙sob linkovanφ. Dßvejte si ale pozor na to, ₧e konfigurace projektu je rozd∞lena pro Release a Debug re₧im. Musφte ji nastavit nejlΘpe pro oba re₧imy, ale hlavn∞ pro Release, proto₧e tuto verzi pak distribuujete.

Mßm n∞jakou t°φdu (nap°φklad CMujEdit zd∞d∞n² od CEdit) a mßm ji zobrazenu v panelu ClassView. ObΦas se stane nßsledujφcφ v∞c, kterΘ nerozumφm: p°idßm t°φd∞ pomocφ polo₧ky kontextoveho menu "Add Windows Message Handler" n∞jakou oblu₧nou funkci, pak se mi nelφbφ co d∞lß a jß ji chci odstranit. Pokud ji sma₧u ruΦn∞ p°φmo v k≤du, stejn∞ jako odkaz na nφ v map∞ zprßv a v hlaviΦkovΘm souboru, je vÜe v po°ßdku. Pokud vÜak kliknu v ClassView u p°φsluÜnΘ metody na Delete a potvrdφm, ₧e se majφ odkazy smazat a t∞lo metody zakomentovat, pak se n∞kdy stane, ₧e mi celß t°φda zmizφ z ClassView a zp∞t se mi objevφ teprve potΘ, co pomoci ClassWizardu znovu p°idßm smazanou metodu. Kdy₧ ji nßsledn∞ vyma₧u "ruΦn∞", je vÜe v po°ßdku. ╚φm to je zp∙sobeno?
ClassView nenφ dokonalΘ. Pokud vyma₧ete kousek klφΦovΘho slova "class", tak t°φda z ClassView zmizφ a to je v po°ßdku, proto₧e v²vojovΘ prost°edφ tuto t°φdu nenajde, ale obΦas se stane, ₧e t°φda zmizφ p°i normalnφ operaci s t°φdou jako je nap°φklad p°idßvßnφ a mazßnφ funkcφ. Toto je chyba samotnΘho v²vojovΘho prost°edφ a ani nejnov∞jÜφ SP (Service Pack) tuto chybu neopravuje. Pokud se vßm stane, ₧e t°φda zmizφ, pokuste se vratit krok, po kterΘm t°φda zmizela a poslΘze ho prove∩te znovu. Pokud nejde krok vrßtit, musφte bu∩to Φekat a₧ se jednoho krßsneho dne t°φda znovu objevφ nebo by m∞lo staΦit vyjmout a zase p°idat hlaviΦkov² i implementaΦnφ soubor, ve kterΘm je t°φda. Zkuste restartovat VC++ i cely poΦφtaΦ a poslednφ mo₧nost je, ₧e vyma₧ete soubory s p°φponami .ncb a .opt v adresß°i vaÜeho projektu. To jsou soubory, ve kter²ch je ulo₧ena prßv∞ struktura ClassView a vy tak p°inutφte VC++, aby ji znovu vytvo°ilo.

Existuje n∞jakΘ freeware v²vojovΘ prost°edφ pro jazyk C/C++ a kde jej mohu zφskat?
Ano, existuje Dev-C++ a stßhnout si ho m∙₧ete na tΘto adrese: www.bloodshed.nu. NovΘ Dev-C++ by m∞lo b²t k dispozici na ChipCD.

Nahoru


Dotazy k C++

Co je to ukazatel?
Ukazatel je druh prom∞nnΘ, jejφ₧ hodnota je adresou v pam∞ti. Pomoci ukazatel∙ se dß d∞lat mnoho v∞cφ, kterΘ vÜak p°i ÜpatnΘm pou₧itφ mohou vest k chybßm v programu. Ukazatele se nap°. pou₧φvajφ pro dynamickou alokaci pam∞ti (tedy p°φmo za b∞hu programu). P°edßni parametru pomoci ukazatele mß za nßsledek, ze se kopφruje jen 4bajtova adresa v pam∞ti a nemusφ se kopφrovat cely objekt (pole, t°φda), kter² m∙₧e b²t velice rozsßhl². Ukazatele se takΘ pou₧φvajφ k p°edßvßnφ parametru odkazem, kdy m∙₧eme uvnit° funkce zm∞nit p°edan² parametr, co₧ jinak nenφ mo₧nΘ.

Jak mohu objektu CStatic zm∞nit ikonu za b∞hu programu?
T°φda CStatic obsahuje Φlenskou funkci SetBitmap(), kterou lze zm∞nit zobrazovan² obrßzek.  

Cht∞l by jsem se Vßs zeptat jak se dß v novΘm VC++ .NET napsat star² dobr² .exe program?
VÜechny typy projekt∙ z verze 6.0 najdete i ve verzi .NET. ProblΘm je, ₧e n∞kterΘ volby jsou trochu zastrΦenΘ. Kdy₧ vytvß°φte nov² projekt ve Visual C++.NET, m∙₧ete si vybrat pouze Win32 Application a teprve na dialogu Wizardu vybφrßte typ aplikace (.exe, .dll, konzole). Pokud vytvß°φte MFC aplikaci, mßte na v²b∞r z n∞kolika mo₧nostφ (zde je to stejnΘ jako ve verzi 6.0): MFC EXE a MFC DLL.

Jak p°evedu °et∞zec na Φφslo?
V knihovnßch C++ existuje °ada funkcφ urΦenΘ ke konverzi °et∞zc∙ na ΦφselnΘ typy a naopak. Funkce atoi() p°evede vstupnφ °et∞zec typu char na celoΦφselnou hodnotu typu int. Funkce rozeznß Φφslo se znamΘnkem, i kdy₧ jsou p°ed samotn²m Φφslem mezery tj. °et∞zec "          -9824" je p°eveden na Φφslo -9824 atd. Krom∞ tΘto funkce m∙₧ete pou₧φt atof() pro p°evod na typ double a atol() na p°evod na typ long. Pokud pou₧ijete funkci atof() nemusφ b²t v °et∞zci p°ed desetinnou teΦkou ₧ßdnΘ Φφslo tj. ".124" se p°evede na Φφslo 0.124. Dßle m∙₧ete pou₧φt formßt "1,05e-34", kter² se p°evede na hodnotu redukovanΘ Planckovy konstanty 1,05.10^-34. Bli₧Üφ informace najdete v nßpov∞d∞ MSDN.
Pokud pou₧φvßte t°φdu CString, lze pou₧φt v²Üe uvedenΘ funkce konverzφ na char.

Jak² je rozdφl mezi cout a printf()?
Ve VC++ je mo₧nΘ pou₧φvat obojφ, cout i printf(). Osobn∞ mßm radÜi printf(), proto₧e umo₧≥uje lepÜφ formßtovßnφ û kratÜφ a p°ehledn∞jÜφ, ale jinak je to zcela na Vßs.

Mohl byste mi vysv∞tlit rozdφl mezi ukazatelem a normßlnφ prom∞nnou? ProΦ n∞kterΘ funkce cht∞jφ jako parametry ukazatele a jinΘ normßlnφ prom∞nnou?
VÜimn∞te si, ₧e nap°. funkce SelectObject() bere jako parametr ukazatel na objekt. Kdy₧ se funkci p°edßvß parametr hodnotou (to znamenß jako normßlnφ prom∞nnou bez hv∞zdiΦky), ud∞lß se kopie p°edßvanΘho objektu na stacku. Kdy₧ se jednß o objekt, musφ se ud∞lat kompletnφ kopie, vÜechny prom∞nnΘ! P°edstavte si, ₧e objekt bude mφt 20 prom∞nn²ch a navφc m∙₧e obsahovat dalÜφ objekty û to jist∞ uznßte, ₧e je znaΦn∞ neefektivnφ, kdy₧ pak tuto kopii stejn∞ zahodφte. Mnohem lepÜφ je, kdy₧ p°edßte pouze ukazatel. Tak₧e obecn∞ platφ, ₧e kdy₧ p°edßvßte objekty je lepÜφ pou₧φvat ukazatele, i kdy₧ nechcete objekt uvnit° funkce m∞nit. Naopak u b∞₧n²ch typ∙ se p°edßvß hodnota, samoz°ejm∞ pokud chcete hodnotu prom∞nnΘ ve funkci m∞nit, musφte p°edat bu∩ ukazatel nebo referenci.

Je lepÜφ Java nebo C++, a v Φem?
Nedß se °φci, jestli je lepÜφ Java nebo C++. Za prvΘ, ka₧d² jazyk mß svΘ p°ednosti a svΘ nev²hody. Za druhΘ se jednß o dva r∙znΘ typy programovacφch jazyk∙. I kdy₧ je syntaxe velice podobnß, C++ je jazyk kompilovan² tzn. ₧e program se jednou p°elo₧φ a pak u₧ se jen spouÜtφ. Ale Java je jazyk interpretovan² tzn. ₧e se k≤d p°eklßdß p°i ka₧dΘm spuÜt∞nφ. Proto takΘ C++ nemß sv∙j skriptovacφ jazyk (znßme JavaScript, VBScript, ale C++Script nikoliv:). Tak₧e by se dalo °φci, ₧e program v C++ bude v₧dy rychlejÜφ ne₧ stejn² program v Jav∞, ale takΘ to zßle₧φ na mnoha dalÜφch okolnostech.

Pou₧φvß se v C++ v deklaraci prom∞nnΘ slovo var, co to var znamenß?
Nepou₧φvß. KlφΦovΘ slovo var se pou₧φvß v Pascalu k deklaraci prom∞nn²ch a k p°edßvßnφ parametr∙ funkcφm odkazem. Jinak var je z°ejm∞ od slova variable, co₧ je prom∞nnß.

Na zßklad∞ vaÜeho kurzu jsem se zaΦal uΦit programovacφ jazyk C, za pou₧itφ knihy "UΦebnice jazyka C 1.". Mßm vÜak problΘm: v₧dy kdy₧ zkompiluji sv∙j program, ten se zpustφ,ale po provedenφ vÜech p°φkaz∙ se ihned ukonΦφ a jß nejsem schopen zkontrolovat sprßvnost v²poΦt∙ na obrazovce. Po zkuÜenostech s Pascalem jsem hledal v knize n∞jak² p°φkaz podobn² READKEY, ale nic takovΘho jsem nenaÜel. Mß jazyk C n∞jak² podobn² p°φkaz? Nebo je chyba v mΘm kompileru?
Chyba to nenφ. Program prost∞ skonΦφ a v²stupnφ okno se zav°e. Pokud je v²poΦet programu rychl², Φlov∞k post°ehne jen probliknutφ. ┌pln² ekvivalent funkci READKEY z Pascalu v C nenajdete, ale m∙₧ete pou₧φt funkci getchar(), kterß funguje podobn∞ (navφc vracφ ordinßlnφ Φφslo stisknutΘho znaku). Abyste mohli tuto funkci pou₧φt, musφte vlo₧it hlaviΦkov² soubor stdio.h.

Bude plynul² p°echod z C++ na C#?
Snad ano. C# mß b²t n∞co mezi Visual Basicem a Visual C++, tak₧e prost°edφ bude z°ejm∞ "p°ßtelÜt∞jÜφ", ale stßle se bude pou₧φvat jazyk C++. Nynφ s odstupem Φasu m∙₧u tento dotaz doplnit. O C# se °φkß, ₧e je spojenφm toho nejlepÜφho z jazyk∙ C++, Visual Basic a Java. SkuteΦn∞, kdy₧ se podφvßte na syntaxi, tak je velice podobnß Jav∞ a p°esto nejde o interpretovan² jazyk. C# je zcela objektov∞ orientovan² jazyk urΦen² pro novou platformu .NET. Pro toho, kdo se uΦφ C++ bude p°echod na C# velice rychl².

Nahoru


Dotazy k DirectX

Sna₧φm se vykreslit n∞jakΘ polygony, ale nic nenφ vid∞t? Jak mßm postupovat v tomto p°φpad∞, kdy₧ si myslφm, ₧e vÜe mam nastavenΘ sprßvn∞?
Za prvΘ je t°eba zjistit, jak je na tom osv∞tlenφ scΘny. ╚asto se stßvß, ₧e nenφ nic vid∞t jenom kvuli tomu, ₧e je prost∞ tma. Tak₧e pokud pou₧φvßte sv∞tlo (nastavenφ pomocφ SetRenderState()) je t°eba mφt n∞jakΘ sv∞tlo vytvo°enΘ a takΘ mφt sprßvnΘ normßlovΘ vektory. M∙₧ete si pomoci hodnotou D3DRS_AMBIENT v metod∞ SetRenderState(), Φφm₧ nastavφte globßlnφ osv∞tlenφ scΘny, tak₧e pak uvidφte i neviditelnΘ. Za druhΘ zjist∞te, zdali mßte sprßvnΘ po°adφ vertex∙ (nebo index∙) v bufferu. Musφ b²t po sm∞ru hodinov²ch ruΦiΦek! Tento test lze vypnout hodnotou D3DRS_CULLMODE v SetRenderState(), nastavφte-li hodnotu parametru D3DCULL_NONE, pak jsou vid∞t i vertexy s opaΦn²m po°adφm vertex∙.

Jak kreslit p°φmo do povrchu DD?
Objekt povrchu mß metodu
Lock(), kterß vracφ ukazatel na vlastnφ pole bufferu! PodrobnΘ informace najdete v nßpoved∞ MSDN. PotΘ co zavolßte Lock() m∙₧ete pomocφ uvedenΘho ukazatele p°istupovat p°φmo do pam∞ti. Nakonec je t°eba zavolat metodu Unlock().

Cht∞l bych se zeptat, jak²m zp∙sobem naprogramovat v DirectX t°eba 2D morphing - plynul² p°echod mezi dv∞mi bitmapami. Tipuju ₧e se kreslφ do n∞jakΘ offscreen plochy. Zajφmß m∞ jak se tam kreslφ? Pokud to lze p°φm²m p°φstupem jako p°i zßpisu do pam∞ti, tak pak se chci zeptat jak a jak² formßt mß ta off-screen plocha.
Do jin²ch povrch∙ (i do offscreen) kreslφte ·pln∞ stejn∞ jako nap°φklad do back bufferu. Jen jako cφlov² buffer vyberete vßÜ offscreen buffer. Plynul² p°echod m∞ napadß jen pomocφ aplha blendingu coz je ovÜem v DD dost velk² problem (vlastnφ DD ho ani nepodporuje). NaÜel jsem n∞jakou knihovnu kde to Ülo, ale nebylo to zcela ideßlni (dost pomalΘ). Mnohem jednoduÜφ je v tomto p°φpad∞ pou₧φt Direct3D. V DD byste leda mohl pou₧φt n∞jak² algoritmus, kter² aplikujete na ka₧d² pixel v²slednΘho povrchu (jako zdrojove pixely budou slou₧it pixely z tech dvou bitmap a n∞jak² integer, jako stupe≥ p°echodu). Tento zp∙sob bude ale velmi pomaly:(

Prßv∞ jsem objevil vaÜi uΦebnici DirectX, a lφbφ se mi, ale jß programuji v Borland C+ + Builder a tak jsem se cht∞l zeptat, jestli by mi uvedenΘ p°φklady fungovali a celkov∞ o kompatibilit∞ kurzu.
Dßle jsem se hct∞l zeptat, jak² je rozdφl mezi Visual C++ a Borland C++ Builder a kter² z nich je lepÜφ a taky pou₧φvan∞jÜφ.

Obßvßm se, ze v m²ch p°φkladech vyu₧φvßm MFC a tam kde tomu tak je, bude ßas Borland bezradn²:( Jinak DD jako takovΘ by snad m∞l n∞jak podporovat, ale nejsem si jist² nebo¥ osobne programuji v MSVC, kde mß DX velkou podporu v podobe SDK a jinych aplikacφ. Nevφm to p°esn∞, ale myslφm, ₧e se vφce pou₧φvß MSVC ne₧ Borland, nebo¥ jak jsem °φkal mß mnohem v∞tÜi podporu (nap°φklad MFC). Borland mß sice takΘ vlastnφ knihovny pro Windows, ale urcite nebudou obsahovat tolik v∞cφ. M∙j nßzor je: Borland na programovani v cΘΦku ano, ale na programovani ve Windows je lepÜφ MSVC. Kurz C++ by m∞l b²t kompatibilni s vaÜφm prost°edφm.

Co je to sprite?
Odpov∞∩ byste jist∞ naÜli v n∞kterΘm kurzu DirectX. Sprite je z anglickΘho p°ekladu n∞co jako duch:-) Sprite je vlastn∞  vykreslovan² obrßzek. Sprite je v∞tÜinou vytvo°en z bitmapy, kterou naΦtete z externφho souboru. Pokud budete mφt pohybujφcφ se letadlo, prßv∞ letadlo bude sprite. Za sprite m∙₧eme pova₧ovat nap°φklad tlaΦφtko menu nebo kurzor myÜi.

Jak zakomponovat zvuk do stßvajφcφch projektu DirectX?
Asi nejlepÜφm °eÜenφm je pou₧φt dalÜφ komponentu DirectX a tou je DirectMusic. Tato komponenta umo₧≥uje, jak p°ehrßvßnφ hudby, tak i samostatn²ch zvuk∙. DirectMusic ΦßsteΦn∞ nahrazuje komponentu DirectSound, kter² je rovn∞₧ k dispozici, ale °ekl bych, ₧e s DirectMusic se lΘpe pracuje. Mßm v plßnu ud∞lat mal² kurz DirectMusic, kde vysv∞tlφm zßklady, abyste mohli svou aplikaci ozvuΦit. Nebude to ovÜem nic podrobnΘho.V p°φÜtφm dφle DirectX se budu tomuto tΘmatu v∞novat.

Poznßmka k jin²m verzφm Visual C++ a DirectX SDK.
Praktick²m zkouÜenφm jsem zjistil, ₧e s nov²m DX SDK 8.0 pracuje pouze Visual C++ 6.0 a vyÜÜφ. Na ni₧Üφch verzφch nelze projekty z kurz∙ zkompilovat kv∙li z°ejmΘ nekompatibilit∞. Proto pokud vlastnφte verzi 4.0 nebo 5.0 nem∙₧ete pou₧φvat DirectX 8.0. DirectX SDK 8.0 vyÜlo na ChipCD vydßnφ 11/01.

Existuje Φesky psanß kniha o DirectX?
Bohu₧el jsem o takovΘ publikaci neslyÜel. V angliΦtin∞ je takov²ch knih n∞kolik (viz. www.microsoft.com).

Bude nejaky serißl o DirectShow?
Nebude. Po DirectDraw bych cht∞l pokraΦovat komponentou DirectInput a pak jeÜt∞ nevφm, ale DirectShow to nebude.

Je mo₧nΘ vytvß°enφ off-screen surfaces v∞tÜφch ne₧li je velikost primary surface?
Podle dokumentace k DirectDraw je to od verze 5.0 mo₧nΘ, ovÜem za nßsledujφcφch podmφnek. Pro umφst∞nφ do video pam∞ti karty je nutnΘ ov∞°it pomocφ metody rozhranφ DirectDraw GetCaps() flag DDCAPS2_WIDESURFACES, kter² se nachßzφ v ΦlenskΘ prom∞nnΘ dwCaps2 prvnφ struktury DDCAPS p°edanΘ metod∞ GetCaps(). V p°φpad∞ vytvo°enφ extrΘmn∞ velkΘho surface se vÜak m∙₧e stßt, ₧e se vytvo°enφ neprovede, aΦkoliv ovladaΦ v²Üe uveden² flag uvßdφ. V tom p°φpad∞ je vrßcen chybov² k≤d DDERR_INVALIDPARAMS. Tyto tzv. ÜirokΘ surfaces (wide surfaces) jsou v₧dy podporovßny v systΘmovΘ pam∞ti. Ve verzφch starÜφch je velikost off-screen surface omezena velikostφ primßrnφho surface.

Nahoru


KrßtkΘ p°φklady

2. Nevφte, jak se dß v C++ vytvo°it dynamicky alokovanΘ pole ukazatel∙ na int?

Vφme. StaΦφ pou₧φt pointer na pointer na integer. Nejprve vytvo°φte pole ukazatel∙ na integer, potom p°es ukazatele v tomto poli vytvo°ite pole integeru. Srozumiteln∞jÜφ bude spφÜ ukßzka:

#include "stdafx.h"
#include <stdio.h>

int **pp_pole;
typedef int *PINT; 
int main(int argc, char* argv[])
{
    pp_pole = NULL;
    pp_pole = new PINT[10]; 
    pp_pole[0] = new int[1];
    pp_pole[1] = new int[2];
    pp_pole[2] = new int[4];
    pp_pole[0][0] = 5;
    pp_pole[1][0] = 6;
    pp_pole[1][1] = 7;
    pp_pole[2][0] = 8;
    // atd. 
    printf("V poli jsou:\n%u\n%u %u\n", pp_pole[0][0], pp_pole[1][0], pp_pole[1][1]);

    return 0;
}

1. Program pro p°evod Φφsla z desφtkovΘ soustavy do binßrnφ

1. Trocha teorie

Vezmeme desφtkovΘ Φφslo a stßle ho celoΦφseln∞ d∞lφme dv∞ma, zbytek po tomto d∞lenφ sepφÜete a pak odspoda p°eΦtete Φφslo vyjßd°enΘ ve dvojkovΘ soustav∞. Tedy nap°φklad pro 157:

Operace V²sledek Zbytek
157 : 2 78 1
78 : 2 39 0
39 : 2 19 1
19 : 2 9 1
9 : 2 4 1
4 : 2 2 0
2 : 2 1 0
1 : 2 0 1

A p°eΦteme zespoda. Tedy: (157)dec = (10011101)bin.

2. Praxe 

Prom∞nnΘ:

length je dΘlka binßrnφho Φφsla, m∙₧ete ale zvolit pevn∞.
retezec je ji₧ alokovanΘ pole znaku o dostateΦnΘ velikosti (max. poΦet znaku bin. Φφsla + 1 znak na ukonΦovacφ \0) d∞lφme bitov²m posunem, kdy prost∞ zahodφme nejmΘn∞ v²znamn² bit a tφm se Φφslo vyd∞lφ dv∞ma. V²sledn² °et∞zec je vytvß°en od konce.

Vlastnφ program:

if(0 == cislo) // osetrime 0
{
    retezec[length - 2] = '0';
}
else
{
    short index = length-1;
    while(cislo > 1)
    {
        retezec[--index] = (char)('0' + (cislo % 2));
// zbytek dame do spravne pozice
        cislo >>= 1;
// vydelime dvema (bitovy posun)
    }
    retezec[--index] = '1';
}

Nahoru

Ond°ej BuriÜin a Ji°φ Formßnek