Alokacja tablicy dwuwymiarowej w funkcji

0

Chciałbym się was zapytać drodzy programiści,w jaki sposób poprawnie alokować pamięć na tablicę dwuwymiarową w funkcji, w języku C?
W obecnym przykładzie przekazuję tablice przez wskaźnik, ale niestety w funkcji zaalokuj_pamiec() : dla linijki:

    *macierz[i] = (float*)malloc(kolumny * sizeof(float));

dostaję błąd:

    Exception thrown at 0x008C1EB5 in Macierz.exe: 0xC0000005: Access violation writing location 0xCCCCCCCC.
void zaalokuj_pamiec(float *** macierz, int wiersze, int kolumny)
{
    *macierz = (float**)malloc(wiersze * sizeof(float));
    if (macierz == NULL)
        printf("Nie udalo sie zaalokowac pamieci");

    for (int i = 0; i < wiersze; i++)
    {
        *macierz[i] = (float*)malloc(kolumny * sizeof(float));
        if (macierz[i] == NULL)
            printf("Nie udalo sie zaalokowac pamieci");
    }
}

void wprowadzanie_wartosci_macierzy(float ** macierz, int ilosc_wierszy, int ilosc_kolumn)
{
    for (int i = 0; i < ilosc_wierszy; i++)
    {
        for (int j = 0; j < ilosc_kolumn; j++)
        {
            printf("T[%d,%d] = ", i + 1, j + 1);
            scanf_s("%f", &macierz[i][j]);
        }
    }
}

inline void wyswietlanie(float **macierz, int w, int k)
{
    for (size_t i = 0; i < w; i++)
    {
        printf("\n");
        for (size_t j = 0; j < k; j++)
        {
            printf("%1.f", macierz[i][j]);
        }
    }
}

inline void zwolnij_miejsce(float ** macierz, int wiersze, int kolumny)
{
    for (int i = 0; i < wiersze; i++)
        free(macierz[i]);

    free(macierz);
}

int main()
{
    int wiersze = 2;
    int kolumny = 3;
    float  ** macierz = NULL;

    zaalokuj_pamiec(&macierz, wiersze, kolumny);
    wprowadzanie_wartosci_macierzy(macierz, wiersze, kolumny);
    zwolnij_miejsce(macierz, wiersze, kolumny);

    system("pause");

    return 0;
}

Dziękuję za poświęcony czas.

2

Spróbuj: (*macierz)[i], bez nawiasu, najpierw zadziała operator [].

2

Uważaj na priorytety operatorów! [] ma wyższy priorytet niż *! https://en.cppreference.com/w/c/language/operator_precedence
Sprawdzaj NULL sensownie!

void zaalokuj_pamiec(float *** macierz, int wiersze, int kolumny)
{
    assert(macierz); // nie ma sensu jeśli NULL!
    *macierz = (float**)malloc(wiersze * sizeof(float));
    if (*macierz == NULL) {
        printf("Nie udalo sie zaalokowac pamieci");
        return;
    }
    for (int i = 0; i < wiersze; i++)
    {
        (*macierz)[i] = (float*)malloc(kolumny * sizeof(float));
        if ((*macierz)[i] == NULL)
            printf("Nie udalo sie zaalokowac pamieci");
    }
}

Są lepsze na to sposoby, jeden kawałek pamięci:

float** mallocFloatMatrix(int rows, int columns)
{
     float **m= malloc(rows * sizeof(float*) + sizeof(float) * rows * columns);
     if (!m) return m;

     float *row = (float *)(m + rows);
     for (int i = 0; i < rows; ++i, row += columns)
         m[i] = row;

     return m;
}
0

Dzięki za odpowiedz, od teraz będę używać tego drugiego sposobu, jest o wiele bardziej intuicyjny ;)!

1

Da się jeszcze ładniej:
https://wandbox.org/permlink/4nREzHY14QUAwKu7

typedef struct MatrixFloat
{
    int rowCount;
    int columnCount;
    float *a[];
} MatrixFloat;

MatrixFloat* MatrixFloatAlloc(int rowCount, int columnCount)
{
    MatrixFloat* m =  malloc(sizeof(MatrixFloat) 
                             + rowCount * sizeof(float*) 
                             + sizeof(float) * rowCount * columnCount);

    if (!m) return m;

    m->rowCount = rowCount;
    m->columnCount = columnCount;

    float *row = (float *)((float **)m->a + rowCount);
    for (int i = 0; i < rowCount; ++i, row += columnCount)
         m->a[i] = row;

    return m;
}

void MatrixFloatFree(MatrixFloat* m)
{
    free(m);
}

Da się nawet jeszcze bardziej pro, ale to już bardziej skomplikowane i mniej poręczne dla początkujących.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0