Diskuze: c - ujištění se ohledně pointerů
V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.
Zobrazeno 13 zpráv z 13.
K personalizaci obsahu a reklam, poskytování funkcí sociálních médií a analýze naší návštěvnosti využíváme soubory cookie. Informace o tom, jak náš web používáte, sdílíme se svými partnery pro sociální média, inzerci a analýzy. Partneři tyto údaje mohou zkombinovat s dalšími informacemi, které jste jim poskytli nebo které získali v důsledku toho, že používáte jejich služby.
Používáme nezbytné cookies pro fungování webu a s tvým souhlasem také analytické a marketingové cookies.
Zajišťují základní funkce, bezpečnost a služby, které sis vyžádal. Nelze je vypnout.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| ITnetwork | ITnetwork | Provoz webu, relace, přihlášení a uložení nastavení cookies. | PHPSESSID, auth_token, sid, itn_consent_impression, __Host-itn_consent | Relace až 1 rok |
| Google Tag Manager | Správa značek a načítání měřicích nástrojů webu. | Žádné | Neukládá se | |
| Google Fonts | Načítání typografie webu. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele | |
| Google Hosted Libraries | Načítání potřebných knihoven a stylů webu. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele | |
| Google reCAPTCHA | Ochrana formulářů a webu před zneužitím. | _GRECAPTCHA, rc::a, rc::b, rc::c, rc::f | Relace až 180 dní | |
| YouTube | Přehrávání vloženého video obsahu. | localStorage, IndexedDB; cookies after playback interaction | Relace až trvalé úložiště | |
| Vimeo | Vimeo | Přehrávání vloženého video obsahu. | __cf_bm, _cfuvid, vuid, localStorage, IndexedDB | Relace až 2 roky |
| Facebook Login | Meta | Přihlášení pomocí účtu třetí strany. | Úložiště řízené poskytovatelem | Relace až 1 rok |
| GoPay | GoPay | Zpracování uživatelem vyžádané platby. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele |
Pomáhají nám porozumět používání webu a zlepšovat ho.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| Google Analytics 4 | Měření návštěvnosti a používání webu. | _ga, _ga_* | Až 2 roky | |
| Microsoft Clarity | Microsoft | Měření návštěvnosti a používání webu. | _clck, _clsk, _cltk | Relace až 1 rok |
Slouží k měření kampaní, personalizaci reklamy a marketingové komunikaci.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| Google Ads | Měření kampaní, reklama a remarketing. | _gcl_au, _gcl_ls | Relace až 90 dní | |
| Meta Pixel | Meta | Měření kampaní, reklama a remarketing. | _fbp, _fbc, localStorage | Až 90 dní |
| Sklik | Seznam.cz | Měření kampaní, reklama a remarketing. | retargeting, sid, szn:* | Relace až trvalé úložiště |
| LinkedIn Insight | Měření kampaní, reklama a remarketing. | bcookie, li_gc, lidc, __cf_bm | Relace až 1 rok | |
| Ecomail | Ecomail.cz | Měření kampaní, reklama a remarketing. | ecmid, Úložiště řízené poskytovatelem | Dle podmínek poskytovatele |
| Atribuce kampaní ITnetwork | ITnetwork | Přiřazení návštěvy a objednávky ke kampani. | campaign_clid[*], user_session_context | Až 1 rok |
V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.
nespadne to na prvnim radku metody main na access violation? 
Ne, ale padá mi to na acces violation, když si chci to pole vrátit přes funkci. A tady jsem už bezradná. Proč to spadne když tam to místo pro pointer na stukturu alokované mám?
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char * jmeno; int vek;
}Osoba;
Osoba ** osobyAlok() {
Osoba ** osoby = (Osoba**)malloc(2 * sizeof(Osoba*));
Osoba a; a.jmeno = "Karel"; a.vek = 32;
Osoba b; b.jmeno = "Robot"; b.vek = 5;
osoby[0] = (Osoba*)malloc(sizeof(Osoba));
osoby[1] = (Osoba*)malloc(sizeof(Osoba));
osoby[0] = &a;
osoby[1] = &b;
return osoby;
}
int main() {
Osoba ** osoby = osobyAlok();
if (osoby != NULL) {
printf("%s, %d let\n", osoby[0]->jmeno, osoby[0]->vek);
printf("%s, %d let \n", osoby[1]->jmeno, osoby[1]->vek);
}
free((void**)osoby); osoby = NULL;
return 0;
}
Zapisuje do promenne jmeno , ktera neni naalokovana - pokud
to nehodi access violation hned, tak tim prepise nekde neco jinyho, ta sance na
accessviolation je tam podle me celkem velka 
Na tom prvnim radku v main to nespadne urcite, ta struktura je slokovana na stacku. Promenna jmeno je jenom pointer, stejne tak retezcovy literal.
Ve funkci OsobyAlok vytváříš dvouprvkové pole ukazatelů na strukturu Osoba. Tyto odkazy nasměruješ na struktury a a b, které jsou ale lokálními proměnnými. To znamená, že jakmile vykonávání funkce skončí, de facto přestanou existovat.
Realita je obvykle taková, že místo, kde tyto proměnné byly (a kam tedy odkazují ty dva ukazatele) stále existuje, jen je zaplněno jinými daty (pokud vůbec nějakými). Ty se je pak pokusíš interpretovat jako strukturu Osoba, ale protože tam už pravděpodobně jsou uložena jiná data, dostaneš se do problémů (zejména proto, že jméno osoby je ve struktuře uloženo jako ukazatel na první znak (Cčkový řetězec)... a hodnota toho ukazatele je (potom, co ty lokální proměnné přestaly existovat), řekněme, náhodná, a tedy obvykle vede na neexistující oblast paměti).
Děkuji za objasnění
.
Jinak teď jsem trochu experimentovala a zkusila napsat toto v té funkci
osobyAlok:
//osoby[1] = &b;
*osoby[1] = b;
nevím ale teda co přesně to znamená, ale funguje to
, v mainu to ty osoby vypíše. A
ještě bych se chtěla zeptat jak naplňovat pole ve funkci, jestli to jde tím
řádkem jak jsem teď napsala nebo se to řeší jinak. Děkuji.
Jo vlastne, "Karel" bude nejspis nekde staticky sedet na stacku, takze se do
a.jmeno jen hodi ukazatel na tohle misto. 
Já bych spíš řekl, že "Karel" bude staticky alokovaný pro celou aplikaci, tím si už úplně jistý nejsem, ale pamatuji si, že když jsem kdysi otevřel .exe zkompilovaný z C kódu v textovém editoru, tak tam ty řetězcové literály byly vidět, z toho soudím, že to bude spíš kompletně statické.
Všechny řetězcové literály definované v kódu jsou staticky alokovány v datovém segmentu binárky. Standardní také je, že pokud máte v kódu více stejných literálů (třeba několikrát přiřazeno "Ahoj", tak se alokuje pouze jednou.
Proto je chyba, když člověk udělá něco takovéhoto:
char *mujstring = "Ahoj";
char *jinystring = "Ahoj";
mujstring[0] = 'a';
Pokud by vám to systém dovolil, tak si přepíšete oba stringy. Typicky to
ale bude segfault, protože oblast statických dat je chráněná proti zápisu

Tento řádek
*osoby[1] = b;
překopíruje strukturu Osoba uloženou v proměnné b (člen po členu) na adresu zapsanou v Osoby[1]. Jelikož jsi ten paměťový blok předtím alokovala, tak to bude fungovat. Já bych tam osobně ještě přidal nějakou tu kulatou závorku, protože se v prioritách operátorů moc neorientuju:
*(osoby[1]) = b;
Ono se to dá i trochu odvodit. Víš, že proměnná Osoby má typ Osoba **, proměnná b má typ Osoba. Operátory * a [] oba lze chápat jako něco, co ti z datového typu argumentu odebere jedno přesměrování (jednu *), takže výsledek je takový, že na obou stranách přiřazovacího příkazu máš něco s datovým typem Osoba. A přiřazení znamená kopírování obsahu (pokud jsme v C).
Zobrazeno 13 zpráv z 13.
