2016-01-29 3 views
2

У меня есть следующая программа, где у меня есть структура. Я собираюсь присвоить ему некоторые значения и записать их в файл. Но путаница здесь, я только что объявил указатель на структуру и не выделил память. Тогда как работает назначение переменной? Я способен правильно извлечь значения из файла «/ главная/информация»Будет ли выделена память для указателя структуры typedef?

#include <stdio.h> 
#define FILEE "/home/info" 

typedef struct my_info 
{ 
    int i; 
    int j; 
    int k; 
    int l; 
}_my_info; 

void main() 
{ 
    _my_info *my_info; 
    int fd; 
    FILE *fp; 
    my_info->i=100; 
    my_info->j=300; 
    my_info->k=200; 
    my_info->l=400; 
    fp = fopen(FILEE,"w"); 
    if (fp == NULL) 
     printf("Error in opening file\n"); 
    fd=fwrite(my_info, sizeof(_my_info), 1, fp); 
    if (fd<0) 
     printf("Error while writing\n"); 
    fclose(fp); 
} 
+0

Если вы пишете на '* my_info', не выделяя что-то во-первых, это неопределенное поведение. Зачем вам нужен указатель? Почему бы просто не использовать стек и объявить '_my_info my_info'? – e0k

+1

Не работает. Кажется, похоже, что он работает. Это может сломаться позже. –

+1

3 примечания; 1 - пространство имен * struct * и * global namespace * являются отдельными, поэтому вы можете сделать 'typedef struct my_info {...} my_info;' без конфликта и 2, вы также можете просто объявить typedef только для этой структуры 'typedef struct {...} my_info; 'и 3, вы можете просто объявить статический экземпляр в своем коде (например,' _my_info my_info; 'и пробел будет зарезервирован, вы должны использовать оператор * dot * (например,' my_info.i = 100; 'и т. Д.) –

ответ

1

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

Вкратце - это работает случайно.

1

Поскольку вы не инициализировали переменную указателя, ее значение является случайным, это означает, что указатель указывает на некоторый случайный адрес. При обращении к адресу, в зависимости от вашей ОС, это может быть сбой или просто получить некоторые данные об мусоре.

3

При объявлении my_info

_my_info *my_info; 

будет иметь неопределенное значение. В вашем случае значение my_info находится в пределах допустимых адресов памяти для ОЗУ. Поэтому напишите ему, и чтение из него состоится.

Однако вы не знаете, какую другую память вы меняете из-за этого. Это может привести к повреждению памяти, особенно в более крупных программах.

1

Существует несколько проблем с вашим текущим кодом. До достижения этого вопроса структуры, вы, кажется, путают значение возврата из write и fwrite с:

fd=fwrite(my_info, sizeof(_my_info), 1, fp); 
if (fd<0) 
    printf("Error while writing\n"); 

fwrite возвращаемого значение типа size_t. Он может никогда быть менее 0. Если вы скомпилируете с предупреждениями (например, -Wall -Wextra), вы всегда будете получать предупреждение о сравнении, всегда проверяя ложь.

Что касается места для вашей структуры, почему вы объявляете указатель? Если у вас нет какой-либо основной причины в вашем примере для объявления указателя, просто объявите статический экземпляр структуры, чтобы хранилище было автоматически зарезервировано. Если вы объявляете указатель, необходимо затем выделить пространство (например, _my_info *my_info = malloc (sizeof *my_info); или _my_info *my_info = calloc (1, sizeof *my_info);)

Для примера, кроме прохождения через осуществление динамического распределения, нет никаких причин, чтобы объявить указатель, просто объявить экземпляр. Ниже приведен краткий пример использования экземпляра и записи/чтения значений из файла.(примечание: комментарии относительно int main() - и изменение имени файла по умолчанию для /tmp/info.bin):

#include <stdio.h> 

#define FILEE "/tmp/info.bin" 

typedef struct { 
    int i; 
    int j; 
    int k; 
    int l; 
} _my_info; 

/* main is type 'int', has arguments and returns a value */ 
int main (int argc, char **argv) 
{ 
    _my_info my_info, my_info2; /* static instances */ 
    /* write to given filename, or FILEE (default) */ 
    FILE *fp = fopen (argc > 1 ? argv[1] : FILEE, "wb"); 

    if (!fp) { 
     fprintf (stderr, "error: file open failed '%s'.\n", argv[1]); 
     return 1; 
    } 

    my_info.i = 100; 
    my_info.j = 300; 
    my_info.k = 200; 
    my_info.l = 400; 

    if (fwrite (&my_info, sizeof my_info, 1, fp) < 1) { 
     fprintf (stderr, "error: write to '%s' failed\n", 
       argc > 1 ? argv[1] : FILEE); 
     return 1; 
    } 
    if (fclose(fp) == EOF) goto errclose; 

    printf ("\n values written to : %s\n", argc > 1 ? argv[1] : FILEE); 

    /* reopen file for reading, read values into my_info2 */ 
    fp = fopen (argc > 1 ? argv[1] : FILEE, "rb"); 
    if (fread (&my_info2, sizeof my_info2, 1, fp) < 1) { 
     fprintf (stderr, "error: read from '%s' failed\n", 
       argc > 1 ? argv[1] : FILEE); 
     return 1; 
    } 

    if (fclose(fp) == EOF) goto errclose; 

    printf (" values read from : %s\n\n", argc > 1 ? argv[1] : FILEE); 
    printf (" my_info2.i : %d\n my_info2.j : %d\n" 
      " my_info2.k : %d\n my_info2.l : %d\n\n", 
      my_info2.i, my_info2.j, my_info2.k, my_info2.l); 

    return 0; 

    errclose: 
    fprintf (stderr, "error: EOF returned on stream close.\n"); 
    return 1; 
} 

Выход

$ ./bin/struct_write 

values written to : /tmp/info.bin 
values read from : /tmp/info.bin 

    my_info2.i : 100 
    my_info2.j : 300 
    my_info2.k : 200 
    my_info2.l : 400 

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

+0

Спасибо за ваш комментарий David.I просто хотел знать, как работает указатель-структура. – Karthick

+1

Конечно, надеюсь, что это помогло. В двух словах, при работе с структурами вы просто определяете «У меня есть структура или указатель для структуры? »Если у вас есть структура, то вы используете оператор'.. 'для доступа к элементам, с указателем вы используете оператор '' -> ''. Если у вас есть структура и берете адрес структуры (например, '& structname'), у вас есть указатель на * structname *. Если вы объявляете структуру, вы получаете автоматическое управление памятью, с указателем, вы должны выделить ':)' –

Смежные вопросы