IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
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: Dynamické pole pointrů na struktury

Aktivity
Avatar
Michal Pánek:16.1.2022 0:35

nejde mi přidělit pamět pointru na pole pointrů ukazujících na struktury

Zkusil jsem:

#include <stdlib.h>

#define MAX_POLOZEK 10

typedef struct{
    char znacka[11];
    char velikost[4];
    char typ[11];
    int cena;
}TYP;

TYP **p_polozka_cislo;
p_polozka_cislo = (TYP **) malloc(MAX_POLOZEK * sizeof(TYP *));

Chci docílit: při pokusu o přidělení paměti mi vscode píše: (pro funkci malloc)
function call is not allowed in a constant expressionC/C++(59)

 
Odpovědět
16.1.2022 0:35
Avatar
Michal Pánek:16.1.2022 1:44

mozna uz v poradku...pred tim jsem mel novy typ struktury definovany v .c souboru a po presunuti definice do hlavickoveho souboru zadna chyba.

 
Nahoru Odpovědět
16.1.2022 1:44
Avatar
Odpovídá na Michal Pánek
Michal Pánek:16.1.2022 2:10

tak po sestaveni programu stale chyba

 
Nahoru Odpovědět
16.1.2022 2:10
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Michal Pánek
DarkCoder:16.1.2022 10:03

Deklarace typu i alokace dynamického pole ukazatelů na strukturu je v pořádku. Chybu máš v jiné části programu.

V následujícím programu je alokováno 10ti prvkové pole ukazatelů na strukturu, každému ukazateli je přiřazena tatáž adresa a nakonec proveden výpis struktury pomocí ukazatelů na strukturu uložených v dynamicky alokovaném poli.

#include <stdio.h>
#include <stdlib.h>

#define MAX_POLOZEK 10

typedef struct {
        char znacka[11];
        char velikost[4];
        char typ[11];
        int cena;
} TYP;

int main(void) {
        TYP zbozi = { "NIKE", "L", "T-Shirt", 590 };
        TYP** p_polozka_cislo = NULL;

        p_polozka_cislo = (TYP**)malloc(MAX_POLOZEK * sizeof(TYP*));
        if (!p_polozka_cislo) {
                fprintf(stderr, "Chyba alokace pameti.\n");
                exit(1);
        }

        for (int i = 0; i < MAX_POLOZEK; i++) p_polozka_cislo[i] = &zbozi;

        for (int i = 0; i < MAX_POLOZEK; i++) {
                printf("index %d: ", i);
                printf("%s, ", p_polozka_cislo[i]->znacka);
                printf("%s, ", p_polozka_cislo[i]->velikost);
                printf("%s, ", p_polozka_cislo[i]->typ);
                printf("%d\n", p_polozka_cislo[i]->cena);
        }

        free(p_polozka_cislo);
        p_polozka_cislo = NULL;

        return 0;
}
Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
16.1.2022 10:03
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Michal Pánek:16.1.2022 10:52

ty jsi vytvoril strukturu v hlavnim souboru.c a ve funkci main jsi potom vytvoril pole a alokoval pro nej pamet coz mi taky funguje.
ja jsem v "hlavnim_soubo­ru.c", kde je i funkce main nic z tohoto kodu nemel.
vyvoril jsem soubor "pole.c a v nem bez jakekoli funkce jsem napsal kus kodu vyse a to se mi nechtelo prelozit a navic jsem potreboval novy typ struktury sdilet.
Tak jsem vytvoril halvickovy souboru "definice.h" kam jsem dal vsechny typedef a definovane promene a funguje mi to.
jen porad nevim proc byl problem definovat pole pointru v jinem modulu a take v nem alokovat dynamicky pamet

 
Nahoru Odpovědět
16.1.2022 10:52
Avatar
Michal Pánek:16.1.2022 11:16

ted jsem zkusil nekolikrat kus kodu:

TYP **p_polozka_cislo = NULL;
p_polozka_cislo = (TYP **) malloc(MAX_POLOZEK * (sizeof(TYP *)));

vlozit kamkoli mimo funkci main a vzdy preklad selhal

 
Nahoru Odpovědět
16.1.2022 11:16
Avatar
Odpovídá na Michal Pánek
Michal Pánek:16.1.2022 11:40

uz to vidim ten pointer mohu definovat mimo funkci, jako jine promenne, ale alokaci pameti musim zavolat ve funkci jinak chyba

 
Nahoru Odpovědět
16.1.2022 11:40
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Michal Pánek
DarkCoder:16.1.2022 12:00

Deklarace nových typů se zapisují do hlavičkových souborů. Deklaraci lze v programu zapsat opakovaně, definici pouze jednou. Vložením hlavičkového souboru do zdrojového souboru poskytujeme informaci o typu, který se nachází v hlavičkovém souboru. Proměnná deklarovaná uvnitř funkce je viditelná pouze v této funkci. Proměnná deklarovaná vně funkce je viditelná všem funkcím v daném souboru. Pokud chceme rozšířit viditelnost globální proměnné, pak je třeba v souboru, ve kterém ji chceme zpřístupnit, používat extern. Ač deklarace proměnné i volání funkce malloc() jsou v obojím případě příkazy, musí být funkce malloc() volána uvnitř nějaké funkce. Proměnné lze deklarovat uvnitř nebo vně funkce.

Nahoru Odpovědět
16.1.2022 12:00
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Michal Pánek:16.1.2022 21:20

prosím Vás,
příkazem

free(&p_polozka_cislo[0]); // sizeof ma 8B - nemohu pouzit protoze promenna pointer na pointer, který ukazuje na strukturu - je staticky definovan
free(p_polozka_cislo[0]); // sizeof ma 8B - uvolním část  alokované paměti pro jeden pointer na strukturu
free(*p_polozka_cislo[0]); // sizeof má 26B - uvolním část alokované paměti a to na pro jednu strukturu

takze kdyz budu chtit vymazat kterykoli i-ty prvek(strukturu), tak zadam

free(*p_polozka_cislo[i]);
p_polozka_cislo[i] = NULL;

a v pripade potreby mohu znovu alokovat pamet, proto novy prvek(strukturu) a priradit mu adresu

p_polozka_cislo[i] = alokuj_pamet();

mota se mi to a nevim jestli tomu rozumim

 
Nahoru Odpovědět
16.1.2022 21:20
Avatar
Michal Pánek:16.1.2022 21:21

oprava take nemohu pouzit - musm priradit hodnotu NULL

free(p_polozka_cislo[0]);
 
Nahoru Odpovědět
16.1.2022 21:21
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Michal Pánek
DarkCoder:17.1.2022 2:02

Takto to nefunguje. Nelze uvolnit pouze část alokované paměti z celého alokovaného bloku. Uvolnit lze pouze celou alokovanou paměť naráz, žádnou nebo realokovat stávající, což by ale v případě mazání jednoho záznamu bylo dosti neefektivní. Řeší se to tzv. dvojí alokací. První alokace udává to, na čem se bude stavět (dynamicky alokované pole, spojový seznam, či jiná datová struktura), druhá alokace udává objekt, na který se chceme odkazovat (v našem případě dynamicky alokovaná struktura). Ukazatele na takto dynamicky alokované struktury se přiřadí ukazatelům dynamicky alokovaného pole. Pak mohu vytvářet a odebírat jednotlivé objekty dle potřeby.

V níže uvedeném programu ukazuji výše popsanou techniku. Vytvářím tam nové záznamy a ukazatele na ně si uchovávám v poli. Nakonec všechny záznamy zruším, stejně tak jako zruším pole s ukazately na tyto záznamy. Lze samozřejmě vytvořit méně záznamů, kam je uložíme si rovněž lze určit. Pokud bych nevyužil celé pole pro záznamy, bylo by nutné nejprve všechny ukazatele nastavit na NULL. Tak lze poznat, který ukazatel v sobě udržuje adresu objektu a který ne a tedy se kterým ukazatelem lze pracovat a který blok paměti uvolňovat.

#include <stdio.h>
#include <stdlib.h>

#define MAX_POLOZEK 10

typedef struct {
        char znacka[11];
        char velikost[4];
        char typ[11];
        int cena;
} TYP;

int main(void) {
        TYP** p_polozka_cislo = NULL;

        // alokace pole ukazatelu na strukturu
        p_polozka_cislo = (TYP**)malloc(MAX_POLOZEK * sizeof(TYP*));
        if (!p_polozka_cislo) exit(1);

        // alokace struktur a prirazeni zacatku pridelene pameti ukazatelum
        for (int i = 0; i < MAX_POLOZEK; i++) {
                p_polozka_cislo[i] = (TYP*)malloc(sizeof(TYP));
                if (!p_polozka_cislo[i]) exit(1);
        }

        // Zde prace se strukturami
        // ...

        // uvolneni pameti vsech alokovanych struktur
        for (int i = 0; i < MAX_POLOZEK; i++) {
                free(p_polozka_cislo[i]);
                p_polozka_cislo[i] = NULL;
        }

        // uvolneni pameti alokovaneho pole ukazatelu na strukturu
        free(p_polozka_cislo);
        p_polozka_cislo = NULL;

        return 0;
}
Nahoru Odpovědět
17.1.2022 2:02
"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 11 zpráv z 11.