Posted in: Různé, Studijní materiály, Vývoj počítačů

Dynamická alokace paměti v C

Aneb ďábel v podobě ukazatele

Globální proměnné

#include <stdlib.h>;
#include <stdio.h>;
//globalni promene udavajici hodnoty pro cely program
int x = 2;
const int y = 3; //y je konstantou
//hlavni funkce programu
void main()
{
	//lokalni promene
	int z = 5;
	//kontrolni vypis hodnot promennych
	printf("Hodnota promene x je %d, hodnota y je %d a hodnota z je %d \n", x, y, z);
	//zastinenni promenne y, jeji redefinice
	int y = 9;
	printf("Hodnota promene x je %d, hodnota y je %d a hodnota z je %d \n", x, y, z);
	printf("Press any key to continue...");
	getchar();
}

Definice ukazatele

#include <stdio.h>
#include <stdlib.h>
void main()
{
    int a; //alokace proměnné a
    int *p_a; //alokace ukazatele
    a = 56; //uožení hodnoty do proměnné a
    p_a = &a; //uložení adresy proměnné a do ukazatele p_a
    printf("Proměnná a s hodnotou %d je v paměti uložená na adrese %p", a, p_a);
    *p_a = 2; //zápis hodnoty 2 na adresu v ukazateli
    printf("\nUkazatel p_a má hodnotu %d a ukazuje na hodnotu %d", p_a, *p_a);
}

Dynamicky alokovaná paměť

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

int main()
{
    int velikost; //určuje počet jednotek, pro které se bude alokovat paměť
    do //ošetření vstupu
    {
        printf("Zadej pocet cisel: "); //výzva uživateli k zadání početu
        if (scanf("%d", &velikost) == 1) //ošetření vstupu
        {
            getchar();
            break;
        }
        else
        {
            printf("Nebylo zadano cele cislo, opakuj zadani\n");
        }
    } while (1); //konec osetreni vstupu
    float *p_i;
    printf("Pokousim se alokovat prostor pro %d cisel...", velikost);
    //dynamická alokace paměti na haldě
    p_i = (float *) malloc(sizeof(float)*velikost);
    //kontrola úspěšnosti alokace paměti
    if (p_i == NULL) //výpis chyby alokace a ukončení programu
    {
        printf("Nedostatek paměti!");
        return (-1);
    }
    //uvolnění paměti
    printf("\nUvolnuji uspesne alokovanou pamet...");
    free(p_i); //samostné uvolnění paměti z haldy
    p_i = NULL; //vymazání ukazatele
    return 0;
}

Procházení bloku paměti

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

void main()
{
    int *p_i, *p_paty;
    // Alokace 100 krát velikosti intu
    p_i = (int *) malloc(sizeof(int) * 100); //dynamická alokace paměti na haldě
    if (p_i == NULL)
    {
        printf("Nedostatek paměti.\n");
        exit(1);
    }
    printf("Alokovana pamet zacina na adrese %p", p_i);
    //vynulování paměti
    for(int i = 0; i < 100; i++)
    {
        p_i[i] = 0; //zápis nuly do daného bloku paměti
    }
    printf("\nNulovani pameti dokonceno");
    //zápis 1 pomocí pointrové aritmetiky - rychlejší postup
    int *p_pozice;
    for (p_pozice = p_i; p_pozice < p_i+100; p_pozice++) //výpočet jednotlivých adres v cyklu
    {
        *p_pozice = 1;
    }
    printf("\nNaplneni pameti jednickami dokonceno");
    free(p_i); // Uvolnění paměti
    p_i = NULL; // Vymazání ukazatele
}

Předávání hodnot referencí

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

void prohod(int *p_a, int *p_b) //parametry jsou ukazatele
{
    int pomocna = *p_a; //ulozeni hodnoty referované ukazatelem p_a do pomocna
    *p_a = *p_b;  //zápis hodnoty z adresy p_b na adresu p_a
    *p_b = pomocna; //uložení původní hodnoty z adresy p_a na adresu p_b
}

void main() {
    int cislo1 = 15; //inicializace proměnné
    int cislo2 = 8; //inicializace proměnné
    prohod(&cislo1, &cislo2); //volání funkce s použitím referenčního operátoru
    printf("V cislo1 je číslo %d a v cislo2 je číslo %d.", cislo1, cislo2);
}

Předávání polí

#include <stdio.h>
#include <stdlib.h>
#define DELKA 10

void napln_pole(int pole[])
{
    for (int i = 0; i < DELKA; i++)
    {
        pole[i] = i + 1; //naplní pole hodnotami 1 až 10
    }
}

void main() {
    int cisla[DELKA]; //deklaruje datovou strukturu pole typu int o 10 prvcích
    napln_pole(cisla); //zavolá funkce napln_pole a předá refeneci na pole
    printf("%d", cisla[5]); // Vypíše číslo 6
}

Výpočet adresy N. prvku paměti

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

void main()
{
    int *p_i, *p_paty;
    // Alokace 100 krát velikosti intu
    p_i = (int *) malloc(sizeof(int) * 100); //dynamická alokace paměti na haldě
    if (p_i == NULL)
    {
        printf("Nedostatek paměti.\n");
        exit(1);
    }
    printf("Alokovana pamet zacina na adrese %p", p_i);
    p_paty = p_i + 4; // Výpočet adresy pátého prvku
    printf("\n5. prvek alokovane pameti lezi na adrese %p", p_i);
    *p_paty = 56; // Uložení hodnoty na pátý prvek
    printf("\n5. prvek alokovane pameti obsahuje hodnotu %d", *p_paty);
    free(p_i); // Uvolnění paměti
    p_i = NULL; // Vymazání ukazatele
}

Callock

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

int main()
{
       int *b; //ukazatel na int
       b = (int *)calloc(200, sizeof(int)); //vytvoří pole o 200 intech
       if (b == NULL)
       {
             printf("Nedostatek paměti");
             return (-1);
       }
       else
       {
             printf("Úspěšně alokováno");
       }
       free(b); //uvolnění alokované paměti
       return 0;
}

Reallock

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

int main() 
{
  int *b; //uakzatel na int
  b = (int *)calloc(10, sizeof(int)); //vynulované dynamické pole pro 10 intů
  if (b == NULL)
  {
    printf("Nedostatek paměti");
    return (-1);
  }
  for (int i = 0; i < 10; i++)
  {
    b[i] = i * 10; //naplnění hodnotami 0 až 90 po desítkách
  }
  int *temp; //pomocný ukazatel
  //není vhodné ukládat o původního ukazatele, protože při neúspěchu
  //realokace bychom přišli o původní pole
  temp = (int *) realloc(b, sizeof(int) * 11); //realokace pole, které je o 1 položku větší
  if (temp == NULL)   //validace úspěčné realokace
  {
    printf("Nedostatek paměti");
    free(b);
    return (-1);
  }
  else
  {
    b = temp; //b ukazuje na nově realokovanou paměť
  }
  b[10] = 100; //zápis do nově aplokované části pole b
  for (int i = 0; i < 11; i++)
  {
    printf("%d", b[i]);   //výpis hodnot ze zvětšeného pole
  }
  free(b); //uvolnění pole b z paměti
  b = NULL; //zrušení ukazatele b
}

Dynamická paměť pro text

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

void main()
{
    char buffer[101]; //pomocný statický řetězec
    printf("Zadej jméno: ");
    scanf(" %100s[^\n]", buffer); // Načtení jména do pomocné paměti
    // Vytvoření dynamického řetězce
    char* jmeno = (char *) malloc(strlen(buffer) + 1);
    strcpy(jmeno, buffer); // Nastavení hodnoty
    buffer[0] = '\0'; //vymazání vstupu   
    printf("Zadej prijmeni: ");
    scanf(" %100s[^\n]", buffer); //opakovane pouziti bufferu
    char* prijmeni = (char *) malloc(strlen(buffer) + 1); // Vytvoření dynamického řetězce
    strcpy(prijmeni, buffer); // Nastavení hodnoty
    printf("Jmenuješ se %s %s", jmeno, prijmeni);
    free(jmeno); // Uvolnění paměti
}

2D pole

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

int main()
{
  //technika ukazatel na ukazatele
  //dynamické 2D pole pro celá čísla (3x5)
  int **matice; //definuje ukazatel na ukazatele na int
  matice = (int **)malloc(sizeof(int *) * 3); //alokuje paměť pro 3 ukazatele na typ int
  if (matice == NULL)
  {
    printf("Nedostatek pameti");
    return (-1);
  }
  for (int i = 0; i < 3; i++) //projde sadu ukazatelů
  {
    matice[i] = (int *)calloc(5, sizeof(int)); //dynamická paměti pro 5 intů
    if (matice[i] == NULL)
    {
      printf("Nedostatek pameti");
      return (-1);
    }
  }
  //nyní je hotová dynamická alokace paměti a s polem pracujeme jakoí se statickým
  //uložení číslených hodnot 1 - 15 do pole
  int t = 1;
  for (int i = 0; i < 3; i++) //prochází řádky
  {
    for (int j = 0; j < 5; j++) //prochází sloupce
    {
      matice[i][j] = t; //zápis hodnoty t do pole
      t++; //inkrementace proměnné t
    }
  }
  //výpis pole
  for (int i = 0; i < 3; i++) //prochází řádky
  {
    for (int j = 0; j < 5; j++) //prochází sloupce
    {
      printf("%d, ", matice[i][j]);
    }
  }
  //uvolnění paměti
  for (int i = 0; i < 3; i++)
  {
    free(matice[i]); //uvolnění jednotlivých řádků
  }
  free(matice); //uvolnění ukazatele na ukazatele 
  return(0); //ukončení s kódem 0
}

2D pole varianta 2

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

int main()
{
       //dynamické 2D pole
       //technika ukazatel na ukazatele

       //dynamické 2D pole pro celá čísla (libovolná velikost)
       int rady = 0, sloupce = 0;
       //načtení rozměru matice ze vstupu
       do
       {
             printf("Zadej pocet radku a pocet sloupcu oddelene mezerou: ");
             if (scanf_s("%d %d", &rady, &sloupce) == 2)
             {
                    getchar();
                    break;
             }
             printf("Nevalidni vstup, opakuj zadani\n");
             getchar();
       } while (1);
       int **matice; //definuje ukazatel na ukazatele na int
       matice = (int **)malloc(sizeof(int *) * rady);  //alokuje paměť pro ukazatele na typ int
       if (matice == NULL)
       {
             printf("Nedostatek pameti");
             return (-1);
       }
       for (int i = 0; i < rady; i++)    //projde sadu ukazatelů
       {
             matice[i] = (int *)calloc(sloupce, sizeof(int)); //dynamická paměti pro samotné hodnoty
             if (matice[i] == NULL)
             {
                    printf("Nedostatek pameti");
                    return (-1);
             }
       }
       //nyní je hotová dynamická alokace paměti a s polem pracujeme jakoí se statickým
       //načtení čísel ze vstupu do pole
       printf("\n"); //odřádkování výpisu
       for (int i = 0; i < rady; i++)    //prochází řádky
       {
             for (int j = 0; j < sloupce; j++) //prochází sloupce
             {
                    do
                    {
                          printf("Zadej cele cislo: ");
                          if (scanf_s("%d", &matice[i][j]) == 1)   //načtení hodnoty do pole
                          {
                                 getchar();
                                 break;
                          }
                          printf("Nevalidni vstup, opakuj zadani\n");
                          getchar();
                    } while (1);
             }
       }
       //výpis pole
       printf("Obsah pole: \n");
       for (int i = 0; i < rady; i++)    //prochází řádky
       {
             for (int j = 0; j < sloupce; j++) //prochází sloupce
             {
                    printf("%d, ", matice[i][j]);
             }
             printf("\n");
       }
       //uvolnění paměti
       for (int i = 0; i < rady; i++)
       {
             free(matice[i]); //uvolnění jednotlivých řádků
       }
       free(matice); //uvolnění ukazatele na ukazatele 
       return(0); //ukončení s kódem 0
}

Simulace 2D pole 1D polem

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

int main()
{
  //dynamické 2D pole
  //použitím jednoho ukazatele - souvyslý blok paměti

  //dynamické 2D pole pro celá čísla (libovolná velikost)
  int rady = 0, sloupce = 0;
  //načtení rozměru matice ze vstupu
  do
  {
    printf("Zadej pocet radku a pocet sloupcu oddelene mezerou: ");
    if (scanf_s("%d %d", &rady, &sloupce) == 2)
    {
      getchar();
      break;
    }
    printf("Nevalidni vstup, opakuj zadani\n");
    getchar();
  } while (1);
  int *matice; //definuje ukazatel
  matice = (int *)calloc((sloupce * rady), sizeof(int)); //alokuje pro celou matici jako souvislý blok
  if (matice == NULL)
  {
    printf("Nedostatek pameti");
    return (-1);
  }
  //nyní je hotová dynamická alokace paměti a s polem pracujeme jakoí se statickým
  //načtení čísel ze vstupu do pole
  printf("\n"); //odřádkování výpisu
  for (int i = 0; i < rady; i++)    //prochází řádky
  {
    for (int j = 0; j < sloupce; j++) //prochází sloupce
    {
      do
      {
        printf("Zadej cele cislo: ");
        if (scanf_s("%d", &matice[i * sloupce +j]) == 1)  //i * sloupce +j //výpočet reálného jednorozměrného indexu
        {
          getchar();
          break;
        }
        printf("Nevalidni vstup, opakuj zadani\n");
        getchar();
      } while (1);
    }
  }
  //výpis pole
  printf("Obsah pole: \n");
  for (int i = 0; i < rady; i++)    //prochází řádky
  {
    for (int j = 0; j < sloupce; j++) //prochází sloupce
    {
      printf("%d, ", matice[i * sloupce + j]);
    }
    printf("\n");
  }
  //uvolnění paměti
  free(matice); //uvolnění reálně jednorozměrného pole 
  return(0); //ukončení s kódem 0
}
Back to Top