PDA

View Full Version : [C] Errore su array di puntatori


Passy
01-01-2005, 17:11
Sto imarando a usare i C ma come tutti in novellini ho dei problemi con gli array di puntatori...
Come prima cosa copio l'indirizzo dell'indice di un array in un altro poi provo a far ciclare il nuovo array per stampare il valore appena copiato ma l'ultimo valore mi va in Segmentation fault... anche diminuendo il numero di cicli ma va in errore


#include <stdio.h>
#include <stdlib.h>

void copy_array();

void copy_struct();

int main(int argc, char **argv) {

copy_array();

printf("-------------------\n");

copy_struct();

return 0;
}

void copy_array()
{
char** array1;
char** array2;
int i;


array1 = (char**)malloc( sizeof(char) * 20);
array2 = (char**)malloc( sizeof(char) * 20);

for (i = 0; i < 20; i++) {
array1[i] = "prova";
//array1[i] = strcpy(array1[i],array2[i]);
array2[i] = (array1[i]);
printf("%d %s\n",i);
}

for (i = 0; i < 20; i++) {
printf("%d %s\n",i ,array2[i]);
}

free(array1);
free(array2);

}

void copy_struct()
{
typedef struct {
int i;
char* array[];
} stru;

stru* array1;
stru* array2;
int i;


array1 = (stru*)malloc( sizeof(stru) + (sizeof(char)* 20));
array2 = (stru*)malloc( sizeof(stru) + (sizeof(char)* 20));

for (i = 0; i < 20; i++) {
array1->array[i] = "prova1";
//array1[i] = strcpy(array1[i],array2[i]);
array2->array[i] = (array1->array[i]);
}

for (i = 0; i < 20; i++) {
printf("%d %s\n",i ,array2->array[i]);
}

free(array1);
free(array2);

}


Grazie per l'aiuto

Buon anno

VegetaSSJ5
01-01-2005, 18:13
innanzitutto buon anno!!!

per quanto riguarda il tuo problema direi che in copy_array() hai sbagliato a fare la malloc. se tu dichiari char **a; quello è un puntatore di puntatore che serve per realizzare un array di stringhe. facendo come hai scritto tu

a1= (char **) malloc (sizeof(char)*20);

è sbagliato perchè allochi spazio per 20 caratteri e non 20 puntatori a caratteri e poi casti a puntatore di puntatore. direi che si dovrebbe correggere in questo modo:

a1= (char **) malloc (sizeof(char *)*20);

in questo modo allochi spazio per 20 stringhe, ora però devi allocare spazio per ogni stringa, così

for (i=0; i<20; ++i) a1[i]= (char *) malloc (sizeof(char)*15);

in questo modo a1 è un array di stringhe composte da 15 caratteri.
per quanto riguarda la copy_struct() ora non ti posso aiutare sono ancora troppo intontito... :eek:

VegetaSSJ5
01-01-2005, 21:09
ecco la versione funzionante del tuo programma. cmq ho anch'io una domanda da fare. la struttura stru contine un array di puntatori a caratteri di dimensione non fissata. ma proprio perchè la dimensione non è fissata, non si dovrebbe fare anche un

array1->array= (char **) malloc (sizeof(char)*n)??#include <stdio.h>
#include <stdlib.h>

void copy_array();

void copy_struct();

int main(int argc, char **argv) {

copy_array();

printf("-------------------\n");

copy_struct();
system("pause");
return 0;
}

void copy_array()
{
char** array1;
char** array2;
int i;


array1 = (char**) malloc (sizeof(char *) * 20);
array2 = (char**) malloc (sizeof(char *) * 20);


for (i = 0; i < 20; i++) {
array1[i]= (char *) malloc (sizeof(char)*20);
array2[i]= (char *) malloc (sizeof(char)*20);
array1[i] = "prova";
//array1[i] = strcpy(array1[i],array2[i]);
array2[i] = (array1[i]);
printf("%d %s\n",i, array1[i]);
}

for (i = 0; i < 20; i++) {
printf("%d %s\n",i ,array2[i]);
}

free(array1);
free(array2);

}

void copy_struct()
{
typedef struct {
int i;
char* array[];
} stru;

stru* array1;
stru* array2;
int i;


array1 = (stru*) malloc (sizeof(stru));
array2 = (stru*) malloc (sizeof(stru));
//array1->array= (char **) malloc (sizeof(char)*20);
//array2->array= (char **) malloc (sizeof(char)*20);


for (i = 0; i < 20; i++) {
array1->array[i]= (char *) malloc (sizeof(char)*20);
array2->array[i]= (char *) malloc (sizeof(char)*20);
array1->array[i] = "prova1";
//array1[i] = strcpy(array1[i],array2[i]);
array2->array[i] = array1->array[i];
}

for (i = 0; i < 20; i++) {
printf("%d %s\n",i ,array2->array[i]);
}

free(array1);
free(array2);

}

Passy
02-01-2005, 23:42
Esatto grazie funziona!!!!
Per quanto riguarda la tua domanda... Pensavo che:

char* pippo= "pippo";
char** pippo1;

pippo1 = pippo;

pippo1 prende l'indirizzo di pippo e può essere utilizzato... (almeno spero)
Stavo provando a fare una mappa (stile Hashtable di Java) e ho utilizzato un principio simile al programmino che ti ho fatto vedere, per adesso funziona (:bsod:) anche se non ho ancora provato a inserire molti record. Magari fra un pò mi accorco di un comportamente strano.

Se vuoi ti invio il codice

Grazie per la tua cortesia

Ciao a presto

cionci
03-01-2005, 08:53
char* pippo= "pippo";
char** pippo1;

pippo1 = pippo;

Le istruzioni sono sbagliate...

Le stringhe non si dichiarano in quel modo ma così:

char pippo[]= "pippo";

pippo1 = pippo;

E' un assegnamento sbagliato...

Un assegnamento valido è:

pippo1 = &pippo;

Ma bisogna anche vedere il senso che vuoi dargli...

Passy
03-01-2005, 11:23
Hai ragione ma il mio compilatore (gcc 3.3.4) mi da un warming quando scrivo


char* str1;
char str[]="prova";

str1 = &str;

printf("%s \n", str1);


e non quando faccio:


char* str1;
char str[]="prova";

str1 = str;

printf("%s \n", str1);

e l'output è sempre lo stesso :bsod:

Grazie ciao

cionci
03-01-2005, 12:32
Appunto...nel codice sopra avevi dichiarato
char ** str1;

L'assegnazione senza dereference va bene nell'ultimo codice che hai postato...

anx721
03-01-2005, 12:53
Originariamente inviato da cionci
Le stringhe non si dichiarano in quel modo ma così:

char pippo[]= "pippo";




perche non si puo diacharare una stringa cosi:

char* pippo= "pippo";


?

VegetaSSJ5
03-01-2005, 12:58
Originariamente inviato da cionci
pippo1 = pippo;

E' un assegnamento sbagliato...

Un assegnamento valido è:

pippo1 = &pippo;
scusa cionci ma pippo è stato dichiarato com un array, quindi in mmoria la variabil pippo conterrà un indirizzo. prchè quindi è sbagliato far qusto pippo1= pippo;?

Passy
03-01-2005, 13:01
Avrei un'altra domanda.
Che differenze ci sono nelle seguenti dichiarazioni?


typedef struct {
int i;
char* array[];
} my_str;


typedef struct {
int i;
char* array[0];
} my_str;


typedef struct {
int i;
char** array;
} my_str;


Grazie

anx721
03-01-2005, 13:07
Originariamente inviato da VegetaSSJ5
scusa cionci ma pippo è stato dichiarato com un array, quindi in mmoria la variabil pippo conterrà un indirizzo. prchè quindi è sbagliato far qusto pippo1= pippo;?

perche l'array è un puntatore a char, mentre pippo1 è stato dichairato come un puntatore a puntatore a char, quindi &pippo puo essere assegnato a pippo1, ma non pippo che e solo un puntatore e non un puntatore a puntatore

VegetaSSJ5
03-01-2005, 13:11
Originariamente inviato da anx721
perche l'array è un puntatore a char, mentre pippo1 è stato dichairato come un puntatore a puntatore a char, quindi &pippo puo essere assegnato a pippo1, ma non pippo che e solo un puntatore e non un puntatore a puntatore
ops! che sbadato non ci avevo fatto caso! ro convinto che pippo1 fosse stato dichiarato com puntator a char! pardon!;) ragazzi comunque ho una domanda a cui non è ancora stata data una risposta:cmq ho anch'io una domanda da fare. la struttura stru contine un array di puntatori a caratteri di dimensione non fissata. ma proprio perchè la dimensione non è fissata, non si dovrebbe fare anche un

array1->array= (char **) malloc (sizeof(char)*n)??

anx721
03-01-2005, 13:25
cmq ho anch'io una domanda da fare. la struttura stru contine un array di puntatori a caratteri di dimensione non fissata. ma proprio perchè la dimensione non è fissata, non si dovrebbe fare anche un

array1->array= (char **) malloc (sizeof(char)*n)??[

Non so quale sia le''effetto di dichiarare un array senza specificarne la dimensione, che è cosa diversa dal passare un array come parametro formale nella definizione di una funzione. Se dichiari un array senza specificarne il numero di elementi, probabilmente il compilatore assume che si tratti d un array di una sola posizione o di zero..non lo so, di certo un array è uno spazio di memori aallocato staticamente, quindi non bisogna allocare la sua memoria con malloc, difatti l'indirizzo a cui punta un array è immodificabile e il compilatore non compilerebbe neppure

anx721
03-01-2005, 13:31
typedef struct {
int i;
char* array[];
} my_str;


typedef struct {
int i;
char* array[0];
} my_str;


typedef struct {
int i;
char** array;
} my_str;


La differenza sta nel fato che la prima struttura dichiara il campo array come un array di dimensione non specificata (e non so cosa questo comporti) di puntatori a char; una volta creata la struttura bisogna allocare memoria per ciasuno delgli elementi puntati dall'array; la seconda dichiarazione definisce array come un array di zero elementi di puntatori a char...mentre la terza definisce array come un puntatore a puntatore a char: una volta istanziata la struttura bisogna far puntare array a un altra variabile char** o bisogna istanziare esplicitamente la memroia con malloc per creare l'array dinamicamente, e poi utulizzare sempre la malloc per allocare memria per ogni elemento dell'array.

VegetaSSJ5
03-01-2005, 13:32
Originariamente inviato da anx721
Non so quale sia le''effetto di dichiarare un array senza specificarne la dimensione, che è cosa diversa dal passare un array come parametro formale nella definizione di una funzione. Se dichiari un array senza specificarne il numero di elementi, probabilmente il compilatore assume che si tratti d un array di una sola posizione o di zero..non lo so, di certo un array è uno spazio di memori aallocato staticamente, quindi non bisogna allocare la sua memoria con malloc, difatti l'indirizzo a cui punta un array è immodificabile e il compilatore non compilerebbe neppure
e infatti se viene fatta la malloc su un array il compilator non compila. cmq guarda la struttura stru: essa al suo interno contine questa dichiarazion:

char* array[];

quanti lmenti può contner quell'array? di sicuro non uno visto che s compili il programma in qull'array vengono contnute 20 stringhe.

cionci
03-01-2005, 16:47
Originariamente inviato da anx721
perche non si puo diacharare una stringa cosi:

char* pippo= "pippo";


?
Si può fare anche così, ma è più sicuro fare la dichiarazione e l'inizializzazione come ho fatto io...almeno io ho sempre preferito usare questo metodo...

Nel modo sopra la zona di memoria puntata da pippo può essere modificata con un semplice assegnamento...e quindi poterbbe creare notevoli problemi...spesso molto difficili da scovare...

char pippo[] = "pippo";

Inizializzando così si ha un errore in caso si cerchi di assegnare un altro indirizzo al puntatore...

anx721
04-01-2005, 12:51
Qualcuno è riuscito a capire cosa fa il compilatore se si dichiara un campo array di lunghezza non specificata in una struttura ? Per le variabili il compilatore (mingw) dà errore, ma nelle struct lo accetta; ma forse non appartiene neppure a nessuno standard...

VegetaSSJ5
04-01-2005, 12:58
secondo me va a scrivere in una zona casuale dello spazio di memoria del programma. questa è una mia ipotesi ma sicuramente avrò detto una cacchiata...:rolleyes: