Diskuze: c++ efektivita kódu
V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.
Zobrazeno 5 zpráv z 5.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.
edit: koukám že mi v kódu chybí středníky, ale o ty teď tak úplně
nejde
Ani jedna funkce nebude pracovat správně ve všech případech a ani jedna funkce není koncipována správně. Avšak obě funkce budou fungovat v programu správně, první funkce bude efektivnější nežli druhá. Pojďme se podívat proč tomu tak je.
Taková funkce by mohla sloužit pro závodní hru kde po stisku potažmo držení konkrétní klávesy by mohla simulovat přidání plynu a tím i navýšení rychlosti až do maximálně stanovené rychlosti.
Ani jedna funkce nebude pracovat správně ve všech případech:
Datové typy mají své rozsahy. Překročením rozsahu vzniká nesmyslná hodnota, která může mít za následek chybnou funkci programu. Podívejme se na simulace obou funkcí:
#include <stdio.h>
#include <limits.h>
#define MAX_SPEED 100
#define DELTA 10
int main(void) {
int speed;
// Simulace 1. funkce
speed = INT_MAX;
speed += DELTA;
if (speed > MAX_SPEED) speed = MAX_SPEED;
printf("%d\n", speed);
// Simulace 2. funkce
speed = INT_MAX;
if (speed + DELTA < MAX_SPEED) speed += DELTA;
else speed = MAX_SPEED;
printf("%d\n", speed);
return 0;
}
Výsledkem obou simulací je nesmyslná hodnota. Ta vznikla přetečením rozsahu typu. Je na programátorovi, aby funkci ošetřil tak aby byla použitelná v programu.
Avšak obě funkce budou fungovat v programu správně:
Je to proto, že hodnota rychlosti v programu nebude dosahovat tak vysoké hodnoty, při kterém by program nefungoval správně. Ani posun rychlosti nebude velký.
Funkce budou pracovat bude-li platit:
speed <= INT_MAX - DELTA
První funkce bude efektivnější nežli druhá:
První funkce bude vykonávat přiřazení a porovnání, popř.
přiřazení, porovnání a přiřazení.
Druhá funkce má navíc vyhodnocení aritmetického výrazu.
Ani jedna funkce není koncipována správně:
Pokud funkce obsahuje proměnnou, měla by tato proměnná být předávána funkci jako její argument. Jelikož se mění, měl by být funkci předáván ukazatel na tuto proměnnou. Takto jsou funkce koncipovány tak že využívají pro svůj chod globální proměnnou a funkce se tak stává závislá na něčem co je venku a tudíž je tento koncept chybný. Pokud je i_max další proměnná, platí totéž co pro předchozí proměnnou s tím rozdílem, že nemusí být předáván ukazatel. Použití i_max by bylo v pořádku, pokud by se jednalo o makro. V takovém případě bych použil pro makro velká písmena.
Závěrem:
Ač ani jedna funkce není dokonalá, lze obě funkce v programu použít. Z důvodu efektivity je lepší použít první funkci.
Díky za odpověď. Hned mám zase nad čím přemýšlet
A díky za připomenutí o přetečení typu. Jak si člověk patlá furt jen
tak něco pro sebe, tak na tohle moc nemyslí. Příklad s rychlostí byl
inspirující
Proměnná i_max není macro... Celkově se jedná o metodu
třídy. Ve které:
i - jsou aktuální životy.
i_max - je max. životu ( mění se v průběhu hry v
závislosti na vylepšení)
x - je parametr/argument metody třídy která přidává x
života ( spuštěno při léčení )
Ve třídě jsou samozřejmě proměnné popsány inteligentněji.
Záměrně jsem to nějak nerozepisoval. A zjednodušil jsem to takto.
Spíše mi šlo o to co je při návrhu správně ( resp. jak správně
postupovat ). Protože z mého pohledu je správně když mám danou maximální
hodnotu pro nějakou proměnnou která tuto hodnotu nesmí přesáhnout. Tak
nejdříve zjistím zda zvýšení proměnné o x nezpůsobí přesah pokud ne,
tak změním onu proměnnou.
Na stranu druhou je původní funkce (1) asi efektivnější, ale z mého
pohledu ne úplně bezpečná.
Když pominu pokročilejší věci v c++. Je to jako když si rychle napíšeš funkci na procházení int pole.
void funkce ( int * pole, int velikost_pole ){
for (int i = 0; i < velikost_pole; i++){
...;
}
Je to rychlé a funguje to. Jen by to jaksi chtělo minimálně zkontrolovat
zda velikost_pole není menší než 1. Pokud si něco
takového napíšu narychlo pro sebe abych něco ověřil etc. Asi je to OK. Ale
všimnul jsem si že to pak dělám i přímo ve svých projektech. Když je to
rychlé a funguje to... Sic si
programuji jen pro sebe, ale chtěl bych to dělat pořádně. Poslední dobou
se snažím i pomocné funkce psát pečlivěji. Proto mě příklad z knihy (
funkce 1) trochu překvapil.
Jaká je vlastně hranice mezi bezpečným a efektivním kódem? Do jaké
míry je ověření vstupu únosné a kdy už jde o paranoiu?
A jak jsi v závěru napsal:
Ač ani jedna funkce není dokonalá, lze obě funkce v programu použít. Z důvodu efektivity je lepší použít první funkci.
Ze své skromné zkušenosti právě důvod efektivity ( teda alespoň podle
mě to efektivní vždy bylo ) mě stál spoustu "UAAAAAAA" a bolestí hlavy.
Pravda u mě to je i dostatkem
neskromné neznalosti a nezkušenosti.
K přetečení rozsahu typu nedochází tak často. Vyjímkou je typ char, zejména při použití modifikátorů signed a unsigned. Funkce by měly být jednoduché, ošetření platnosti vstupů by mělo být pokud možno řešeno vně funkce. U práce s poli zejména, kde dochází k traversování.
Robustnost aplikace je vždy na prvním místě, optimalizace je vždy bonus. Obě kritéria spolu souvisí, nesmyslné testování může podstatně snížit výkon aplikace. Kdy testovat a kdy ne, k tomu se postupně dopracuješ jak budeš získávat zkušenosti. Jsi části, kdy testování je důležité, opomenutí může způsobit pád programu, jehož příčina může být někdy obtížně dohledatelná.
Je správné, že neopomínáš ladění aplikace. Je to jedna z nejnáročnějších činností, ale nesmírně důležitá.
Zobrazeno 5 zpráv z 5.