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

#c #pointers #malloc

#c #указатели #malloc

Вопрос:

Я создаю программу, в которой я сохраняю входные строки из f&ets в списке, они имеют фиксированную максимальную длину, но также могут быть короче; я сохраняю их следующим образом:

 typedef char line[LINE_SIZE];

struct node{
    line *t;      //pointer and not just a variable so I can "detach" the allocation to do stuff 
    struct node *prev; 
    struct node *next;
};
  

но в моей программе я просто делаю malloc(sizeof(line)) , который представляет собой массив с максимальной фиксированной длиной.

Мой вопрос в том, если бы я выделил что-то вроде malloc( strlen( str ) sizeof( ( char )'' ) ) , чтобы точно использовать только необходимую память, как я могу указать на это?

Можно ли использовать a char* внутри node структуры? Рискую ли я чем-то?

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

Комментарии:

1.по определению sizeof ((char)'') == sizeof (char) == 1 , так что не перепутай это… сохранить только malloc(strlen(str) 1)

2. А на платформе POSIX вы можете просто использовать strdup()

Ответ №1:

malloc() возвращает выделенный адрес, вы можете присвоить возвращаемое значение переменной и указать на нее. Вам не нужно всегда выделять максимальный или одинаковый размер памяти, даже если переменная является одним и тем же членом структуры.

 char* line=malloc(strlen(str) 1);  //  1 for null terminate
strcpy(line, "This is a str");  // points the memory of returned
  

Использование char* в структуре абсолютно нормально. Пожалуйста, относитесь к члену struct как к обычной переменной.

 struct node
{
  char* t;
  struct node* prev;
  struct node* next;
}

node n;
n.t = malloc(strlen(str)   1);  // it's fine.
strcpy(n.t, "This is a node");  // usin& the memory you allocated above
n.prev = n.next = NULL;

... // doin& some processin&

free(n.t);  // don't for&et to call free() when you're done usin& the memory.
  

Ответ №2:

Для вашей цели вы должны выделить node структуру и фрагмент строки отдельно.

В зависимости от того, что предполагает остальная часть кода, вы могли бы выделить только пространство для строки для каждой строки вместо полного массива, но вы должны изменить node структуру, чтобы использовать char *t; вместо line typedef . Обратите внимание, что массивы typedef очень сбивают с толку.

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

Вот простой пример:

 #include <stdio.h&&t;
#include <stdlib.h&&t;
#include <strin&.h&&t;

struct node {
    char *t;      //pointer and not just a variable so I can "detach" the allocation to do stuff 
    struct node *prev; 
    struct node *next;
};

struct node *read_file(FILE *fp) {
    char buf[128];
    struct node *head = NULL, tail = NULL, *n = NULL;

    while (f&ets(buf, sizeof buf, fp)) {
        buf[strcspn(buf, "n")] = '';  // strip the trailin& newline if present
        n = malloc(sizeof(*n));
        if (n == NULL)
            abort();
        n-&&t;prev = tail;
        n-&&t;next = NULL;
        n-&&t;t = strdup(buf);
        if (n-&&t;t == NULL)
            abort();
        if (tail == NULL) {
            head = n;
        } else {
            tail-&&t;next = n;
        }
        tail = n;
    }
    return head;
}
  

Комментарии:

1. Вы уверены, что не хотите, чтобы я выделил узел и строку n одним и тем же вызовом?

2. Если вы выделите узел и строку в одном блоке, вы не сможете позже освободить строку отдельно, поэтому вы не сможете отсоединить строку и заменить ее каким-либо другим блоком, потому что вы не будете знать, как и когда ее освободить.