C - прохождение массивов через функции - PullRequest
0 голосов
/ 24 ноября 2010

У меня есть следующее ...

void keySorter(char (*keys)[NumberOfKeys][LengthOfKeys]) {}

int main ()
{
  char keys[NumberOfKeys][LengthOfKeys] = {};
  keySorter (&keys);
}

Итак, у меня есть это, оно прекрасно компилируется, но я получаю обратно то, что хочу. Ключи [] [] были инициализированы с = {};, поэтому они пустые, но они должны заполняться вещами один раз внутри функции.

Первый элемент помещается в функцию, остальное идет ...? Я наблюдаю за функцией STRCPY, которая помещает данные в ключи [] [] и имеет правильное исходное значение, хотя целевое значение кажется мусором (или, по крайней мере, оно состоит из символов, которые выглядят как мусор).

strcpy(*keys[i], "BLAH");

Это другая часть функции.

Ответы [ 4 ]

2 голосов
/ 24 ноября 2010

Внутри keySorter, keys - указатель на массив массивов char.Это означает, что для получения массива char для использования с strcpy необходимо разыменовать указатель, а затем использовать доступ к массиву для выбора массива.

Например,

strcpy((*keys)[i], "test");

Выне может использовать *keys[i], потому что правила приоритета означают, что [] применяется первым, а keys не указатель на первый элемент массива, это указатель на сам массив.

Кстати, для того, что вы делаете, гораздо более обычным является объявление keySorter как взятие указателя на массив символов и допускание нормального распада указателя на массив в аргументах функции.

void keySorter(char keys[][LengthOfKeys]);

или

void keySorter(char (*keys)[LengthOfKeys]);

В этом случае вы можете просто сделать strcpy(keys[i], "blah"), потому что keys - это указатель на массив массивов char.

Вызывается:

int main ()
{
  char keys[NumberOfKeys][LengthOfKeys] = {};
  keySorter(keys);
}
1 голос
/ 24 ноября 2010

Вот код (C99), который работает - вывод получается аккуратным, если ваше окно имеет ширину более 100 столбцов (установите 32 на меньшее число, если у вас узкие окна):

#include <stdio.h>

enum { NumberOfKeys = 20, LengthOfKeys = 32 };

static void keySorter(char (*keys)[NumberOfKeys][LengthOfKeys])
{
    size_t k = 0;
    for (size_t i = 0; i < NumberOfKeys; i++)
        for (size_t j = 0; j < LengthOfKeys; j++)
            (*keys)[i][j] = ++k & 0xFF;
}

static void dumpKeys(char keys[NumberOfKeys][LengthOfKeys])
{
    for (size_t i = 0; i < NumberOfKeys; i++)
    {
        for (size_t j = 0; j < LengthOfKeys; j++)
            printf("%02X ", keys[i][j] & 0xFF);
        putchar('\n');
    }
}

int main(void)
{
    char keys[NumberOfKeys][LengthOfKeys] = {};
    printf("Before:\n");
    dumpKeys(keys);
    keySorter(&keys);
    printf("After:\n");
    dumpKeys(keys);
}

Обратите внимание на принципиальную разницу между нотациями, используемыми для доступа к массиву в keySorter() по сравнению с dumpKeys(). Во-первых, поскольку передается указатель на 2D-массив, код для доступа к массиву должен сначала разыменовать указатель с помощью (*keys)[i][j], тогда как во втором случае массив передается напрямую, и нотация прямого доступа keys[i][j] в порядке .

Когда я скомпилировал (GCC 4.2.1 на MacOS X 10.6.5), используя:

gcc -O -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
    -Wold-style-definition xx.c -o xx  

указанный код компилируется без ошибок. Когда я экспериментировал с использованием keys[i][j] в keySorter(), он жаловался на «ошибку: несовместимые типы в присваивании».

Вы также можете изменить keySorter(), чтобы использовать strcpy() (вам, конечно, тоже нужно #include <string.h>):

static void keySorter(char (*keys)[NumberOfKeys][LengthOfKeys])
{
    for (size_t i = 0; i < NumberOfKeys; i++)
        strcpy((*keys)[i], "BLAH");
}

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

Если / когда вы написали:

strcpy(keys[i], "BLAH");

тогда вы должны получать предупреждения компилятора (если вы не получаете лучший компилятор или, по крайней мере, решите, как заставить ваш компилятор выдавать обильные предупреждения), но значение keys[0] было первым массивом в наборе массивов, указанном keys, затем keys[1] был вторым массивом, keys[2] был третьим массивом и так далее. Указатель может затухать настолько, что вы в конечном итоге будете писать BLAH над первой строкой каждого массива, но в итоге вы получите дамп ядра или другие подобные проблемы, потому что вы не выделяете достаточное количество массивов в основной программе.

1 голос
/ 24 ноября 2010

Вы объявляете автоматическую переменную keys, но ничего не помещаете в нее, поэтому она будет содержать значения мусора.

Да, вы правильно вставляете массив, в этом вызове и объявленной функциитип параметра соответствует.Но вы передаете указатель на массив массива char вместо простого указателя на первый элемент char массива.Возможно, вам следует сделать это следующим образом:

void keySorter(char keys[NumberOfKeys][LengthOfKeys])
{...}

int main(void)
{
    char  keys[NumberOfKeys][LengthOfKeys];
    keySorter(keys);
}

Это позволяет очень просто получить доступ к элементам массива:

for (int i = 0;  i < NumberOfKeys;  i++)
{
    for (int j = 0;  j < LengthOfKeys;  j++)
    {
        ... keys[i][j] ...
    }
}

Добавление

Добавление явного значения инициализатора достаточно для инициализации массива всеми нулями (т. Е. Всеми значениями '\0' char):

    char  keys[NumberOfKeys][LengthOfKeys] = { 0 };
0 голосов
/ 24 ноября 2010

keys - это уже указатель, поэтому вам не нужно делать этот keySorter (& keys); поставить просто keySorter (ключи);

...