2011-01-01 2 views
0

#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' в массив struct? (и, следовательно, именно поэтому он печатает ненулевое значение)Простые проблемы с массивом C

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

ответ

0

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


Edit:

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

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, который не является allo wed, потому что mem - это просто имя для адреса массива, а не указатель, который может измениться. Поэтому для копирования элементов вам необходимо использовать memcpy.

+0

Что случилось с скрепляющих инициализаторах - при правильном использовании, конечно? Почему они запутывают? –

+0

Это путает * здесь *, потому что он инициализирует массив, а не скаляр. (Например: присваивает ли значение первому элементу или всему массиву? Он даже компилируется? Если нет, это потому, что вы не можете назначить указатель на «char» или из-за чего-то еще? заставляет читателя слишком много думать.) Мне не нравятся они вообще по другим причинам, но это только личный вкус; в этом конкретном случае, я думаю, их лучше избегать. – Mehrdad

+0

Спасибо - memcpy кажется достойным решением. Моя единственная проблема заключается в том, что если я изменю MEM_SIZE на что-то большое, сделаю ли копирование заметное количество времени? – user559865

0
  1. Использование тетсру для копирования данных
  2. Выделяет новую память в Func инициализации, то «фишка» будет восстановлена, когда конец FUNC инициализации.
1

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

#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

Да, мое плохое для двух «мемов». Является ли добавленный _t в mem_t общепринятым способом, которым люди отличаются от типа (size_t, time_t например)? – user559865

+0

Это зависит от того, какие форматы кодирования (или рекомендации) вы следуете. Обычно я предпочитаю это (обычно это следует за множеством * кода NIX): typedef struct foobar_st {int a;} foobar_t; –

+0

Нет, имена, оканчивающиеся на '_t', зарезервированы стандартами, и, вероятно, в какой-то момент вы столкнетесь с реализацией ОС. Поэтому лучше избегать их. – jilles

0

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

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

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

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

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

+0

Почему считается неправильной практикой, чтобы вернуть локальную структуру? – user559865

+0

Технически - вы хотите передать структуру, заполняемую ptr/ref. Вы копируете весь объект структуры, если вы возвращаете структуру из функции. – tperk

+0

О, справедливо. – user559865

0

Для вашего структуры можно использовать неявную STRUCT-контент-копию, как:

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; 
} 
Смежные вопросы