2013-09-24 2 views
0

Я работаю над программой, которая должна обрабатывать файл изображения PGM формыПопутных Структуры в С

P2 
24 7 
11 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 11 11 11 11 0 11 0 0 0 11 0 0 11 0 0 0 11 0 0 0 11 0 0 
0 11 0 0 0 0 11 0 0 0 11 0 11 0 11 0 0 11 11 0 0 11 0 0 
0 11 11 11 11 0 0 11 0 11 0 0 11 11 11 0 0 11 0 11 0 11 0 0 
0 11 0 0 0 0 0 11 0 11 0 11 0 0 0 11 0 11 0 0 11 11 0 0 
0 11 11 11 11 0 0 0 11 0 0 11 0 0 0 11 0 11 0 0 0 11 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 

я иметь следующую структуру для хранения данных и функции инициализации

struct Image { 
    int row, column; 
    int maxValue; 
    unsigned int data[MAXLINELENGTH]; 
} 

Image * Image_Init() 
{ 
    Image tmp_Image; 
    tmp_Image.row = 0; 
    tmp_Image.column = 0; 
    int i; 
    for (i = 0; i < MAXLINELENGTH; i++) 
    { 
     tmp_Image.data[i] = 0; 
    } 
    return &tmp_Image; 
} 

Это дает мне предупреждение о том, что функция возвращает адрес локальной переменной. Я хочу создать в основном объект Image и передать его. Как мне это сделать?

Спасибо

EDIT ===================================

Я, кажется, в состоянии использовать

Image * Image_Init() 
{ 
    Image *tmp_Image; 
    tmp_Image->row = 0; 
    tmp_Image->column = 0; 
    int i; 
    for (i = 0; i < MAXLINELENGTH; i++) 
    { 
     tmp_Image->data[i] = 0; 
    } 
    return tmp_Image; 
} 

Теперь у меня возникают проблемы с тем, где мне нужно читать данные из массива. Я использую ту же базовую структуру

Image * Image_Init_From_Array (unsigned int height, unsigned int width, unsigned int *data) 
{ 
    Image *tmp_Image; 
    tmp_Image->row = width; 
    tmp_Image->column = height; 
    tmp_Image->maxValue = 255; 
    int i; 
    for (i = 0; i < MAXLINELENGTH; i++) 
    { 
     tmp_Image->data[i] = data[i]; 
    } 
    return tmp_Image; 
} 

Это компилируется нормально, но в результате ошибки сегментации.

+0

Вы можете передать указатель на 'tmp_Image' в качестве аргумента в функции' Image_Init'. –

+0

Для части редактирования: tmp_Image является диким указателем в то время, указывая в любом месте и доступ к этой памяти вызывает SEGFAULT – LostBoy

ответ

1

Если вам нужно передать структуру по указателю, ее нужно будет где-то выделить. Вы можете выделить его статически или автоматически и передать указатели на более низкие области (не может передать указатель выше, чем его объем).

my_function() { 
    Image tmp_image; 
    Image_init(&tmp_image); 
    //... 
} 

Или передать его по всему миру, и принять адрес:

Image tmp_image; 

my_function() { 
    Image_init(&tmp_image); 
    //... 
} 

Или передать его динамически:

my_function() { 
    Image *tmp_image; 
    tmp_image = malloc(sizeof(Image)); 
    Image_init(tmp_image); // this time it's already a pointer, so no '&' 
    //... 
} 

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

typedef struct { 
    int row, column; 
    int maxValue; 
    unsigned int data[]; //C99 allows this empty array to do the "struct hack" 
} Image; 

Image *new_Image (int row, int column, int max) { 
    Image *tmp = malloc(sizeof(Image) + row*column); 
    if (tmp != NULL) { 
     tmp->row = row; 
     tmp->column = column; 
     tmp->maxValue = max; 
    } 
    return tmp; 
} 

для ANSI C, вам придется поставить 1 для размера данных массив и вычесть 1 из расчета размера. Вы также можете объявить поле данных как указатель и либо выделить его отдельно, либо как здесь sizeof(Image) + row*columns - как один блок - но вам также нужно будет установить указатель.

+0

. Назначение моего друга говорит, что мы должны передать его в качестве указателей. – Evan

1

Просто передать указатель на изображение:

Image * Image_Init (Image * i) 

Залейте что один из. Вы можете либо вернуть указатель или использовать значение переменной переданный указатель в заходящих функциональных точек на:

В основном:

Image * Image_Init (Image *tmp_Image) 
{ 

     tmp_Image->row = 0; 
     tmp_Image->column = 0; 
     int i; 
     for (i = 0; i < MAXLINELENGTH; i++) 
     { 
     tmp_Image->data[i] = 0; 
     } 
     return tmp_Image; 
} 

void caller() 
{ 
    Image img; 

    Image_Init(&img); 

    // work with img here 
    } 

Для редактирования части: tmp_Image дикое указатель в то время, указывая куда-нибудь и доступ к этой памяти вызовет SEGFAULT.Особенно в этой функции, в которой вы хотите работать с существующим «объектом», вам нужно будет пройти в структурах в качестве указателя:

Image * Image_Init_From_Array (Image * image, unsigned int height, unsigned int width, unsigned int *data) 
{ 
... 
} 
+0

Выполнение 'Image img = {0};' кажется более простым. – alk

+0

Верно, но я предполагаю, что это не было назначение;) – LostBoy

+0

Мы ограничились использованием Image * Image_Init_From_Array (беззнаковая высота, беззнаковая ширина, беззнаковые данные int) и Image * Image_Init(). Нам не разрешено добавлять указатели на внешние объекты. Из программы runme мы имеем Image * i1; i1 = Image_Init_From_Array (10, 20, hi); – Evan

1

Отредактированной функция выделяет память для указателя на Image, но не для Image переменная.

Ваш комментарий к ответу LostBoy говорит, что вы должны соответствовать данной подписи:

Image *i1; 
i1 = Image_Init_From_Array(10, 20, hi); 

Это означает, что Image_Init_From_Array() должен выделить память сама по себе. Вы не можете просто создать переменную Image в функции, так как память для этой переменной будет снова освобождена при выходе из функции.

Эта ситуация типична для malloc().

  • Выделяет память для Image объекта в функции Image_Init_From_Array()
  • возвращает указатель на вновь созданный объект
  • прохода, который указатель на другие функции, которые нуждаются в объекте
  • написать Image_delete(Image *) функции, где вы освободите память, ранее выделенную malloc(). Если вы этого не сделаете, у вас будет утечка памяти.
Смежные вопросы