Altri hanno risposto come malloc(0) lavori. Risponderò a una delle domande che hai posto a cui non è stata ancora data risposta (credo). La domanda riguarda realloc(malloc(0), 0) :
Cosa significa
malloc(0)Restituzione? La risposta sarebbe la stessa perrealloc(malloc(0),0)?
Lo standard dice questo su realloc(ptr, size) :
- se
ptrèNULL, si comporta comemalloc(size), - altrimenti (
ptrnon èNULL), rilascia il vecchio puntatore all'oggetto tramiteptre restituisce un puntatore a un nuovo buffer allocato. Ma sesizeè 0, C89 dice che l'effetto è equivalente afree(ptr). È interessante notare che non riesco a trovare quella dichiarazione nella bozza C99 (n1256 o n1336). In C89, l'unico valore sensato da restituire in quel caso sarebbeNULL.
Quindi, ci sono due casi:
malloc(0)restituisceNULLsu un'implementazione. Poi il tuorealloc()chiamata è equivalente arealloc(NULL, 0). Equivale amalloc(0)dall'alto (e questo èNULLin questo caso).malloc(0)restituisce diverso daNULL. Quindi, la chiamata equivale afree(malloc(0)). In questo caso,malloc(0)erealloc(malloc(0), 0)non equivalente.
Nota che qui c'è un caso interessante:nel secondo caso, quando malloc(0) restituisce diverso da NULL in caso di successo, potrebbe comunque restituire NULL per indicare il fallimento. Ciò risulterà in una chiamata del tipo:realloc(NULL, 0) , che sarebbe equivalente a malloc(0) , che può restituire o meno NULL .
Non sono sicuro se l'omissione in C99 sia una svista o se significhi che in C99, realloc(ptr, 0) per non-NULL ptr non è equivalente a free(ptr) . Ho appena provato con gcc -std=c99 , e quanto sopra è equivalente a free(ptr) .
Modifica :Penso di capire qual è la tua confusione:
Diamo un'occhiata a uno snippet del tuo codice di esempio:
ptr = malloc(0);
if (ptr == realloc(ptr, 1024))
Quanto sopra non è lo stesso di malloc(0) == realloc(malloc(0), 1024) . Nel secondo, il malloc() la chiamata viene effettuata due volte, mentre nella prima si passa un puntatore allocato in precedenza a realloc() .
Analizziamo prima il primo codice. Supponendo malloc(0) non restituisce NULL in caso di successo, ptr ha un valore valido Quando esegui realloc(ptr, 1024) , realloc() fondamentalmente ti dà un nuovo buffer che ha la dimensione 1024 e il ptr diventa invalido. Un'implementazione conforme può restituire lo stesso indirizzo di quello già presente in ptr . Quindi, il tuo if la condizione può restituire true. (Nota, tuttavia, osservando il valore di ptr dopo realloc(ptr, 1024) potrebbe essere un comportamento non definito.)
Ora la domanda che fai:malloc(0) == realloc(malloc(0), 1024) . In questo caso, supponiamo che sia il file malloc(0) sulla sinistra e sulla destra restituisce non-NULL . Quindi, sono garantiti per essere diversi. Inoltre, il valore restituito da malloc() sul lato sinistro non è stato free() d ancora, quindi qualsiasi altro malloc() , calloc() o realloc() potrebbe non restituire quel valore. Ciò significa che se hai scritto la tua condizione come:
if (malloc(0) == realloc(malloc(0), 1024)
puts("possible");
non vedrai possible sull'output (a meno che sia malloc() e realloc() fallisce e restituisce NULL ).
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
void *p1;
void *p2;
p1 = malloc(0);
p2 = realloc(p1, 1024);
if (p1 == p2)
puts("possible, OK");
/* Ignore the memory leaks */
if (malloc(0) == realloc(malloc(0), 1024))
puts("shouldn't happen, something is wrong");
return 0;
}
Su OS X, il mio codice non ha prodotto nulla quando l'ho eseguito. Su Linux, stampa possible, OK .
malloc(0) è Implementazione definita per quanto riguarda C99.
Da C99 [Sezione 7.20.3]
L'ordine e la contiguità dell'archiviazione allocata dalle chiamate successive alle funzioni calloc, malloc e realloc non sono specificate . Il puntatore restituito se l'allocazione ha successo è opportunamente allineato in modo che possa essere assegnato a un puntatore a qualsiasi tipo di oggetto e quindi utilizzato per accedere a tale oggetto o a un array di tali oggetti nello spazio allocato (fino a quando lo spazio non viene esplicitamente deallocato). La durata di un oggetto allocato si estende dall'allocazione fino alla deallocazione. Ciascuna di tali allocazioni produrrà un puntatore a un oggetto disgiunto da qualsiasi altro oggetto. Il puntatore restituito punta all'inizio (indirizzo di byte più basso) dello spazio allocato. Se non è possibile allocare lo spazio, viene restituito un puntatore nullo. Se la dimensione dello spazio richiesto è zero, il comportamento è definito dall'implementazione :viene restituito un puntatore nullo o il comportamento è come se la dimensione fosse un valore diverso da zero, tranne per il fatto che il puntatore restituito non deve essere utilizzato per accedere a un oggetto.
In C89, malloc(0) dipende dall'implementazione - non so se C99 lo abbia risolto o meno. In C++, usando:
char * p = new char[0];
è ben definito:ottieni un puntatore valido, non nullo. Naturalmente, non puoi utilizzare il puntatore per accedere a ciò a cui punta senza invocare un comportamento indefinito.
Per quanto riguarda il motivo per cui esiste, è conveniente per alcuni algoritmi e significa che non è necessario sporcare il codice con test per valori zero.