malloc в C, но использовать синтаксис многомерного массива

<!DOCTYPE html>
<html>
    <body>
        <p id="p1">
            <b>Enter the no of row and column to create table:</b>
            <br/><br/>
            <table>
                <tr>
                    <th>No. of Row(s) </th>
                    <th>No. of Column(s)</th>
                </tr>
                <tr>
                    <td><input type="text" id="row" value="4" /> X</td>
                    <td><input type="text" id="col" value="7" />Y</td>
                </tr>
            </table>
            <br/>
            <button id="create" onclick="create()">create table</button>
        </p>
        <br/><br/>
        <input type="button" value="Reload page" onclick="reloadPage()">
        <script>
            function create() {
                var row = parseInt(document.getElementById("row").value);
                var col = parseInt(document.getElementById("col").value);

                var tablestart="<table id=myTable border=1>";
                var tableend = "</table>";
                var trstart = "<tr bgcolor=#ff9966>";
                var trend = "</tr>";
                var tdstart = "<td>";
                var tdend = "</td>";
                var data="data in cell";
                var str1=tablestart + trstart + tdstart + data + tdend + trend + tableend;
                document.write(tablestart);

                for (var r=0;r<row;r++) {
                    document.write(trstart);
                    for(var c=0; c<col; c++) {
                        document.write(tdstart+"Row."+r+" Col."+c+tdend);
                    }
                }

                document.write(tableend);
                document.write("<br/>");
                var s="<button id="+"delete"+" onclick="+"deleteTable()"+">Delete top Row </button>";
                document.write(s);
                var relod="<button id="+"relod"+" onclick="+"reloadPage()"+">Reload Page </button>";
                document.write(relod);
            }
            function deleteTable() {
                var dr=0;
                if(confirm("It will be deleted..!!")) {
                    document.getElementById("myTable").deleteRow(dr);
                }
            }
            function reloadPage(){
                location.reload();
            }
        </script>
    </body>
</html>
13
задан Claudiu 29 June 2010 в 20:15
поделиться

7 ответов

Да, вы можете это сделать, и нет, вам не нужен другой массив указателей, как вам говорят большинство других ответов. Вам нужен вызов:

int (*MAGICVAR)[200] = malloc(400 * sizeof *MAGICVAR);
MAGICVAR[20][10] = 3; // sets the (200*20 + 10)th element

Если вы хотите объявить функцию, возвращающую такой указатель, вы можете сделать это следующим образом:

int (*func(void))[200]
{
    int (*MAGICVAR)[200] = malloc(400 * sizeof *MAGICVAR);
    MAGICVAR[20][10] = 3;

    return MAGICVAR;
}

Или использовать typedef, что делает его немного понятнее:

typedef int (*arrayptr)[200];

arrayptr function(void)
{
    /* ... */
27
ответ дан 1 December 2019 в 17:29
поделиться

Если дополнительное косвенное обращение не вызывает беспокойства, вы можете использовать массив указателей.

Править

Вот вариант ответа @Platinum Azure, который не делает так много вызовов malloc. Помимо более быстрого распределения, все элементы гарантированно будут смежными:

#define ROWS 400
#define COLS 200

int **memory = malloc(ROWS * sizeof(*memory));
int *arr = malloc(ROWS * COLS * sizeof(int));

int i;
for (i = 0; i < ROWS; ++i)
{
    memory[i] = &arr[i * COLS];
}

memory[20][10] = 3;
4
ответ дан 1 December 2019 в 17:29
поделиться

В том же духе, что и ответ Cogwheel, вот (несколько грязный) трюк, который делает только один вызов malloc () :

#define ROWS 400
#define COLS 200
int** array = malloc(ROWS * sizeof(int*) + ROWS * COLS * sizeof(int));
int i;
for (i = 0; i < ROWS; ++i)
    array[i] = (int*)(array + ROWS) + (i * COLS);

Это заполняет первую часть буфера указателями на каждую строку в следующем, непрерывном массиве данных.

2
ответ дан 1 December 2019 в 17:29
поделиться

Компилятор и среда выполнения не имеют возможности узнать ваши предполагаемые размерности, используя только умножение в вызове malloc.

Вам нужно использовать двойной указатель, чтобы достичь возможности двух индексов. Что-то вроде этого должно получиться:

#define ROWS 400
#define COLS 200

int **memory = malloc(ROWS * sizeof(*memory));

int i;
for (i = 0; i < ROWS; ++i)
{
    memory[i] = malloc(COLS * sizeof(*memory[i]);
}

memory[20][10] = 3;

Убедитесь, что вы проверили все возвращаемые значения malloc на наличие возвратов NULL, указывающих на ошибку выделения памяти.

1
ответ дан 1 December 2019 в 17:29
поделиться
int** memory = malloc(sizeof(*memory)*400); 
for (int i=0 ; i < 400 ; i++) 
{
    memory[i] = malloc(sizeof(int)*200);
}
0
ответ дан 1 December 2019 в 17:29
поделиться

Используйте указатель на массивы:

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

int main()
{
    int (*arr)[10];

    arr = malloc(10*10*sizeof(int));
    for (int i = 0; i < 10; i++)
        for(int j = 0; j < 10; j++)
            arr[i][j] = i*j;

    for (int i = 0; i < 10; i++)
        for(int j = 0; j < 10; j++)
            printf("%d\n", arr[i][j]);
    free(arr);
    return 0;
}
19
ответ дан 1 December 2019 в 17:29
поделиться
#define ROWS 400
#define index_array_2d(a,i,j) (a)[(i)*ROWS + (j)]
...
index_array_2d( memory, 20, 10 ) = -1;
int x = index_array_2d( memory, 20, 10 );

Изменить:

Массивы и указатели выглядят почти одинаково, но компилятор обрабатывает их по-разному.Давайте посмотрим, что нужно сделать для индексации массива и отмены ссылки на указатель со смещением:

  1. Допустим, мы объявили статический массив (массив в стеке немного сложнее, фиксированное смещение от регистра, но, по сути, то же самое):

    статический массив int [10];

  2. И указатель:

    статический int * указатель;

  3. Затем мы отменяем уважение для каждого следующим образом:

    x = array [i];
    x = pointer [i];

Следует отметить, что адрес начала массива , а также адрес указателя (не его содержимое) фиксированы во время ссылки / загрузки. Затем компилятор выполняет следующие действия:

  1. Для массива отмена ссылки:
    • загружает значение i ,
    • добавляет его к значению array , то есть к его фиксированному адресу, чтобы сформировать целевой адрес памяти,
    • загружает значение из вычисленного адрес
  2. Для указатель отмены ссылки:
    • загружает значение i ,
    • загружает значение указателя , то есть содержимое по его адресу,
    • добавляет два значения к формируют действующий адрес
    • загружает значение из вычисленного адреса.

То же самое происходит с 2D-массивом с дополнительными шагами по загрузке второго индекса и его умножению на размер строки (который является константой). Все это решается во время компиляции, и во время выполнения нет возможности заменить одно другим.

Изменить:

@caf здесь имеет правильное решение. В конце концов, в языке есть законный способ индексировать указатель как двумерный массив.

2
ответ дан 1 December 2019 в 17:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: