Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze – Lekce 4 - Dynamické textové řetězce a struktury v jazyce C

Zpět

Upozorňujeme, že diskuze pod našimi online kurzy jsou nemoderované a primárně slouží k získávání zpětné vazby pro budoucí vylepšení kurzů. Pro studenty našich rekvalifikačních kurzů nabízíme možnost přímého kontaktu s lektory a studijním referentem pro osobní konzultace a podporu v rámci jejich studia. Toto je exkluzivní služba, která zajišťuje kvalitní a cílenou pomoc v případě jakýchkoli dotazů nebo projektů.

Komentáře
Avatar
Odpovídá na Martin Russin
Patrik Valkovič:12.7.2021 17:31

Přesně tak. Obdobně by to fungovalo například pokud by se jednalo o ukazatel na celé číslo.

int *p_int = (int*)malloc(sizeof(int));
*p_int = 10; // přiřazení hodnoty na místo kam míří ukazatel
int *p_int2 = p_int; // přiřazení ukazatele do ukazatele, adresa na kterou odkazuje p_int2 je stejná jako ta na kterou odkazuje p_int
int hodnota = *p_int2; // přiřazení hodnoty do hodnoty, dereference získá hodnoty z místa kam ukazatel odkazuje
Odpovědět
12.7.2021 17:31
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Martin Russin
DarkCoder:12.7.2021 18:19

Pozor na to správné vyjadřování, ukazatel není inicializován adresou ukazatele na typ, ale ukazatelem na typ. Adresa ukazatele je něco jiného, jedná se již o vícenásobnou referenci, kterou nelze přiřadit ukazatelové proměnné.

UZIVATEL *p_uzivatel2 = p_Karol;

Výše uvedený kód značí že je definována ukazatelová proměnná p_uzivatel2, která může ukazovat na typ UZIVATEL a tato proměnná je inicializována ukazatelovou proměnnou p_Karol.

Levá strana je adresa, pravá strana musí být adresa. Proto není na pravé straně uveden u názvu proměnné znak *.

Pokud bychom měli toto:

int i = 0;
int *pa = &i;

Pak mohu psát

int *pb = pa;
// Nebo
int *pb = &i;

Ukazatele pa a pb budou ukazovat na stejnou adresu v paměti, na místo, kde je uložena proměnná i.

Co se týká dotazu k parametru. Funkce která má parametr ukazatel ihned značí, že si žádá adresu a ne hodnotu a že hodnota proměnné, na kterou ukazatel ukazuje, může být měněna.

Máme-li prototyp funkce

void func(int *num);

Pak tuto funkci lze volat těmito způsoby

func(&i);
func(pa);
func(pb);

Dereference se pak používají uvnitř funkce pro přístup k hodnotě proměnné, jejíž adresu jsme předali funkci při jejím volání.

Pamatovat: je třeba počty referencí levé a pravé strany přiřazovacího příkazu udržovat v rovnosti. Jakmile se objeví ve funkci či v definici ukazatel, pak této ukazatelové proměnné se předává pouze adresa, nikoli hodnota.

Odpovědět
12.7.2021 18:19
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Jakub Hrbáček:1.6.2022 13:39

Zdravím, rád bych se zeptal na tento příkaz, který jsem potkal někde na internetu.

char *p_t = "ahoj"; //bez alokace a místo char t[] = "ahoj";

Předpokládám tedy, že pravá strana příkazu ("ahoj") vlastně vrátí adresu na nově vytvořené pole charu. A jelikož pole je skoro pointer, tak to funguje. Mohu tedy vypsat obsah pole nebo pracovat s jednotlivými prvky pole:

printf("%s", p_t); //vypíše ahoj
*(p_t + 2) = ...; //změna 2. prvku
p_t[2] = ...; //změna 2. prvku

Ale nefungují příkazy běžně používané při práci s polem charů nebo pointery.

strcpy(p_t, "novy text");
scanf(" %4[^\n]s", p_text);

Lze také přiřazovat nové adresy pointerů:

p_t = scanf("jiny retezec");

Ale mám pocit, že to je docela nebezpečné, když se ta předchozí paměť neuvolní.
Jaký je tedy smysl nahoře zmíněného příkazu a jak s ním pracovat (jestli vůbec). Jinak nacházel jsem to hlavně ve tvaru:

const char* p_t = "ahoj";

Díky.

 
Odpovědět
1.6.2022 13:39
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Jakub Hrbáček
DarkCoder:1.6.2022 15:13

Smyslem tohoto příkazu je vytváření konstantních řetězců. Proto se i dost často píše s modifikátorem const.

char *p_t = "ahoj";
// nebo
const char* p_t = "ahoj";

Funguje to tak že se vytvoří daný řetězec a uloží se do tabulky řetězců. Překladače jej často ukládají do read-only části paměti. Na tento řetězec se předá adresa ukazateli. Díky tomu jej lze používat, číst, nikoli však měnit!

Naproti tomu varianta:

char a[10] = "ahoj";

Funguje tak, že se vytvoří řetězec, uloží se do tabulky řetězců, následně dojde k jeho kopírování do části paměti, která není určena pro čtení, kterou nám překladač přidělil. Tento proces je tedy o něco pomalejší nežli v případě ukazatele, neboť nedochází ke kopírování řetězce.

Na ukazatel lze aplikovat běžné výstupní funkce (printf(), puts()). Avšak jakékoli zápisy mající za úkol změnit řetězec jsou chybné.

*(p_t + 2) = ...; //změna 2. prvku
p_t[2] = ...; //změna 2. prvku

NELZE! Jakýkoli pokus o modifikaci řetězce na který máme ukazatel může vést k nedefinovanému chování.

Dále nelze přiřazovat ukazateli nový řetězec pomoci funkce strcpy().

Řetězec je dostupný po celou dobu chodu programu (static storage) a paměť se uvolní po jeho skončení. Neprovádí se žádná externí dealokace pomocí free().

Pole a ukazatel mají k sobě velmi blízko, nejsou však totéž!

Několik rozdílů pro následující zápisy:

char a[10] = "ahoj";
// a
char* p = "ahoj";

a je konstantní ukazatel, nelze měnit, p je ukazatel, lze měnit
a[0] = 'x'; je platné, p[0] = 'x'; je neplatné
a = "nazdar"; je neplatné, p = "nazdar"; je platné
sizeof(a) je 10 bytů, sizeof(p) jsou 4 byty

Pokud chci používat v programu řetězec, který nechceme měnit, použijeme formu s ukazatelem.
Pokud chci nebo potřebuji řetězec nějakým způsobem měnit, použiji pole.

Odpovědět
1.6.2022 15:13
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
DarkCoder
Člen
Avatar
DarkCoder:1. února 20:23

Dynamické textové řetězce se často vytváří uvnitř funkcí. Proč zde není ukázka toho jak se vrací vytvořený řetězec z funkce?

Odpovědět
1. února 20:23
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 5 zpráv z 25.