Pergunta

Olá, estou trabalhando com C e tenho uma pergunta sobre a atribuição de ponteiros.

struct foo
{
   int _bar;
   char * _car[SOME_NUMBER]; // this is meant to be an array of char * so that it can hold pointers to names of cars
}

int foofunc (void * arg)
{
   int bar;
   char * car[SOME_NUMBER];

   struct foo * thing = (struct foo *) arg;

   bar = thing->_bar; // this works fine
   car = thing->_car; // this gives compiler errors of incompatible types in assignment
}

CAR e _CAR têm a mesma declaração, por que estou recebendo um erro sobre tipos incompatíveis? Meu palpite é que isso tem algo a ver com eles serem indicadores (porque são indicadores de matrizes de char *, certo?), Mas não vejo por que isso é um problema.

Quando eu declarei char * car; ao invés de char * car[MAXINT]; Compila bem. Mas não vejo como isso seria útil para mim mais tarde, quando preciso acessar certas informações usando o índice, seria muito irritante acessar essas informações posteriormente. Na verdade, nem tenho certeza se estou indo da maneira certa, talvez haja uma maneira melhor de armazenar um monte de cordas em vez de usar a matriz de char *?

EDIT: Eu não pretendia usar o INT_MAX (valor máximo de int), é apenas outro INT, que é cerca de 20.

Foi útil?

Solução

Você está criando uma nova matriz de tamanho Maxint. Eu acho que você quer criar um ponteiro para uma variedade de size maxint.

Criando um ponteiro para uma variedade de char*S:

A seguir, é apresentada uma variedade de size maxint para char* elementos:

char * car[MAXINT]; 

A seguir, é apresentado um ponteiro para: uma variedade de size maxint para char* elementos:

char* (*car)[MAXINT];

A seguir, é como você define um ponteiro para: uma matriz de tamanho maxint para char* elementos:

char* (*car)[MAXINT];
car = &arg->_car;

Outros erros de sintaxe na pergunta:

  • Você precisa ter um semicolon após sua definição de estrutura.
  • Você deveria estar usando foo* não foo. Então deve ser:
    struct foo* thing = (struct foo *) arg;
  • Você deveria estar usando thing não arg:
    bar = thing->_bar;
    car = thing->_car;

Outras dicas

car e _car são matrizes e você não pode atribuir matrizes em C (exceto quando a matriz é incorporada em uma estrutura (ou união) e você faz uma atribuição de estrutura).

Eles também são matrizes de ponteiros para char, em vez de ponteiros para matrizes de char. O que você escreveu no código é provavelmente o que você deseja - você pode armazenar indicadores para nomes máximos na matriz. No entanto, você deve descrever o tipo corretamente - como uma variedade de ponteiros para Char ou Char Pointers.

Um ponteiro para uma variedade de personagens seria:

char (*car)[MAXINT];

E um ponto para uma variedade de ponteiros de personagens (obrigado, Brian) seria:

char *(*car)[MAXINT];

Tenha cuidado com o Maxint; Essa pode ser uma matriz muito grande (no Linux, <values.h> define MAXINT Como INT_MAX, que é pelo menos 231-1).


O código se parece:

struct foo
{
   int _bar;
   char * _car[MAXINT];
}

int foofunc (void * arg)
{
   int bar;
   char * car[MAXINT];
   struct foo thing = (struct foo *) arg;
   bar = arg->_bar; // this works fine
   car = arg->_car; // this gives compiler errors of incompatible types in assignment
}

Nem a tarefa de bar nem carro deve compilar - arg é um void *. Você presumivelmente pretendia usar thing de alguma forma ou forma. Como Brian observou, também há problemas lá:

Você quer:

int foofunc(void *arg)
{
    int bar;
    char *car[MAXINT];
    struct foo thing = *(struct foo *)arg;
    bar = thing._bar; // this works fine
    car = thing._car; // this is still an array assignment
    ...other code using bar and car...
}

Ou você quer:

int foofunc(void *arg)
{
    int bar;
    char *car[MAXINT];
    struct foo *thing = (struct foo *) arg;
    bar = thing->_bar; // this works fine
    car = thing->_car; // this is still an array assignment
    ...other code using bar and car...
}

Ou, de fato:

int foofunc(void *arg)
{
    struct foo *thing = (struct foo *) arg;
    int bar           = thing->_bar; // this works fine
    char *car[MAXINT] = thing->_car; // this is still an array assignment
    ...other code using bar and car...
}

Finalmente, lidando com a atribuição de matriz, em c você pode usar razoavelmente memmove() para fazer isso:

int foofunc(void *arg)
{
    struct foo *thing = (struct foo *) arg;
    int bar           = thing->_bar; // this works fine
    char *car[MAXINT];
    memmove(car, thing->_car, sizeof(car));
    ...other code using bar and car...
}

A função semelhante memcpy() não possui semântica confiável se as áreas a serem copiadas se sobrepõem, enquanto memmove() faz; É mais simples sempre usar memmove() Porque sempre funciona corretamente. Em C ++, você precisa ser cauteloso sobre o uso memmove() (ou memcpy()). Nesse código, seria seguro o suficiente, mas entender por que não é trivial.

Você precisa estar ciente de que está apenas copiando ponteiros aqui - você não está copiando as cordas que os ponteiros apontam. Se algo mais mudar essas seqüências, isso afeta os dois valores vistos via car e a variável no código de chamada.

Um último ponto - por enquanto: tem certeza de que precisa do argumento para a função como um void *? Ele abre o código para todos os tipos de abuso que podem ser evitados se a função for declarada como tomar um 'struct foo *'em vez disso (ou mesmo um'const struct foo *').

Você não pode atribuir a uma matriz da maneira que está fazendo. Você pode fazer uma cópia em termos de elemento.

for(int i = 0; i < MAXINT; i++)
{
  car[i] = (arg->_car)[i]
}

Observe que, se as cordas não forem constantes, talvez seja necessário usar strcpy.

A notação de matriz em C é legitimamente confusa; Seu código não significa o que você acha que isso significa.

arg->_car significa "o endereço da matriz _car". De forma similar, car significa "o endereço da matriz car". Se você está tentando copiar o conteúdo de _Car para o carro, isso fará isso:

memcpy(car, _car, MAXINT);

Mas sua verdadeira pergunta, eu acho, é "Qual é a melhor maneira de armazenar uma lista de cordas?" Esta resposta é: uma lista dinâmica (que cresce automaticamente à medida que você adiciona itens).

Você declararia assim:

#define CARSIZE 65
int numCars = 0;
char **car; /* a list of addresses, each one will point to a string */

Para adicionar um carro:

char *newCar = malloc(CARSIZE); /* make room */
strncpy(newCar, "Mercedes", CARSIZE); /* newCar has the address of the string */
car[numCars++] = newCar; /* store it */

Para listar os carros:

int n;
for (n = 0; n < numCars; ++n)
    printf("%s\n", car[n]);

Para remover o carro na posição n:

free(car[n]); /* release the memory */
/* condense the list of pointers */
for ( ; n < numCars - 1; ++n)
    car[n] = car[n+1];

Isso é completamente rotineiro em C. NOTA: O acima está fora do topo da minha cabeça e não é copiado de um programa de trabalho, por isso não posso prometer que todos os * estão no lugar certo. Eu suspeito que esta é uma tarefa de casa, então não quero te dar tudo...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top