Простые проблемы с массивом C - PullRequest
0 голосов
/ 01 января 2011

#include <stdio.h>

#define MEM_SIZE 16

typedef struct memory_contents{
 unsigned char mem[MEM_SIZE]; /* memory */
} mem;

mem init(char prog[]){
 mem chip = {prog};
 return chip;
}

int main(int argc, char *argv[]){
 char memory[MEM_SIZE] = {0}; /* zero out whole array */
 mem chip = init(memory);

 printf("%d\n", chip.mem[0]);
    return 0;
}

Прав ли я, полагая, что этот код (в частности, функция init) пытается поместить адрес переменной 'memory' в массив структуры? (и, следовательно, именно поэтому он печатает ненулевое значение)

Я пытаюсь инициализировать структуру так, чтобы массив mem структуры был параметром prog []. Какой предпочтительный или лучший способ сделать это? Я мог бы сделать mem структуры указателем на первый элемент массива размером MEM_SIZE, но я чувствую, что это может вызвать проблемы: если я изменю массив памяти в main позже, это также изменит значения в массиве чипа. .

Ответы [ 5 ]

1 голос
/ 01 января 2011

Вот рекомендуемый способ сделать это:

#include <stdio.h>

#define MEM_SIZE 16

typedef struct memory_contents{
 unsigned char mem[MEM_SIZE]; /* memory */
} mem_t;

mem_t* init (char* arr)
{
    mem_t* info = (mem_t*) malloc (sizeof (mem_t));
    if (!info)
    return NULL:    /* No memory */

    memcpy (&info->mem, arr, MEM_SIZE);
    return info;
}

int main(int argc, char *argv[])
{
    unsigned char memory[MEM_SIZE] = {1,2,3,4,5,6,0};
    mem_t* chip = init (memory);
    if (!chip)
    return ENOMEM;

    printf("values: %d %d\n", chip->mem[0], chip->mem[1]);

    if (chip)
    free (chip);

    return 0;
}

Еще один момент, на который следует обратить внимание: Старайтесь не использовать имя члена поля структуры и имя структуры.Они могут вызвать много конфликтов.

0 голосов
/ 02 января 2011

Для вашей структуры вы можете использовать неявное struct-content-copy, например:

mem init(char *prog){
 return *(mem*)prog;
}

int main(int argc, char *argv[]){
 char memory[MEM_SIZE] = {0xAA,0xBB,0xCC,0xDD}; /* non zero test values */

 mem chip = init(memory);
 printf("%02X%02X%02X%02X\n",chip.mem[0],chip.mem[1],chip.mem[2],chip.mem[3]);

 memory[1]=0;
 chip = init(memory);
 printf("%02X%02X%02X%02X\n",chip.mem[0],chip.mem[1],chip.mem[2],chip.mem[3]);

 return 0;
}
0 голосов
/ 01 января 2011

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

И, чтобы ответить на ваш вопрос - да.Вы инициализируете массив значением указателя.Инициализация массива, как вы сделали в main с помощью «memory»: char memory [MAX_SIZE] = {0};// инициализация массива.

Выполнение memcpy () является предпочтительным способом сделать это.Также - плохая практика - возвращать локальную структуру из функции - предпочтительным способом является выделение объекта в куче и выполнение memcpy.(Хотя компилятор может оптимизировать это с дополнительным копированием) Это просто ужасная практика.

Если вы знаете структуру массива во время компиляции: другие возможности - это инициализация структуры c99 (обычно это делается в режиме ядра): mem_t memObj = {.mem = {1, 2, 3, 4, 5}};или просто: mem_t memObj = {1, 2, 3, 4, 5};(в вашем примере, поскольку это единственный член)

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

0 голосов
/ 01 января 2011
  1. Используйте memcpy для копирования данных
  2. Выделите новую память в функции func init, «чип» будет восстановлен после завершения функции func.
0 голосов
/ 01 января 2011

Вы не можете изменить указатель mem структуры, потому что это не обычный указатель - имя mem - это просто имя для адреса этого поля.Не инициализируйте массивы, используя нотацию { ... };это просто трудно читать и сбивать с толку (это, конечно, смутило меня ...).Вместо этого используйте memcpy.


Редактировать:

Ваш код не компилируется с моим компилятором:

error C2440: 'initializing' : cannot convert from 'char []' to 'char'
    This conversion requires a reinterpret_cast, a C-style cast or function-style cast

(Ошибка в этой строке:mem chip = {prog};)

Сначала я был озадачен, почему ваш код даже скомпилирован, и после проверки здесь имеет смысл: как я уже говорил выше, вы пытаетесь присвоить массив / указатель для mem, что недопустимо, поскольку mem - это просто имя для адреса массива, а не указатель, который может измениться.Поэтому вы должны использовать memcpy для копирования элементов.

...