проблема с массивом указателей в C - PullRequest
0 голосов
/ 01 сентября 2011

У меня проблема с моей программой.Я пытаюсь запустить через массив указателей.Как только правильный указатель найден, программа напечатает все посещенные указатели.Я получаю сообщение об ошибке по адресу:

void * temp=debut[k]; 
ajouter(temp[k], resultat); 

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

Я не понимаю, почему ???

спасибовам заранее за помощь

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

int calculerTaille(void * pointeur);
void ajouter(void * pointeur, char * resultat[]);
int verifier(void * debut, void * fin);

void * A[3];
void * D[3];
void * F[2];
void * G[4];
void * H[4];
void * J[3];
void * K[5];
void * L[4];
void * M[5];

int i = 0;

char * resultat[100];

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

A[0] = D;
A[1] = H;
A[2] = K;

D[0] = A;
D[1] = G;
D[2] = H;

F[0] = K;
F[1] = L;

G[0] = D;
G[1] = H;
G[2] = J;
G[3] = M;

H[0] = A;
H[1] = G;
H[2] = L;
H[3] = M;

J[0] = G;
J[1] = L;
J[2] = M;

K[0] = A;
K[1] = F;
K[2] = H;
K[3] = L;
K[4] = M;

L[0] = F;
L[1] = J;
L[2] = K;
L[3] = M;

M[0] = G;
M[1] = H;
M[2] = J;
M[3] = K;
M[4] = L;

void * debut = A;
void * fin = J;


ajouter(J, resultat);
while (verifier(debut, fin) != 1) {

    srand(time(0));
    int k = rand() % calculerTaille(K);

    void * temp=debut[k]; //error
    ajouter(temp[k], resultat); //error

}

int l=0;
for(l=0; resultat[l]!=NULL;l++) printf("%s ", resultat[l]);
return 0;
}

void ajouter(void * pointeur, char * resultat[]) {

if (pointeur == A)
    resultat[i] = "A";
if (pointeur == D)
    resultat[i] = "D";
if (pointeur == F)
    resultat[i] = "F";
if (pointeur == G)
    resultat[i] = "G";
if (pointeur == H)
    resultat[i] = "H";
if (pointeur == J)
    resultat[i] = "J";
if (pointeur == K)
    resultat[i] = "K";
if (pointeur == L)
    resultat[i] = "L";
if (pointeur == M)
    resultat[i] = "M";

i++;

}

int verifier(void * debut, void * fin) {
if (debut == fin)
    return 1;
else
    return 0;
}

int calculerTaille(void * pointeur) {
if (pointeur == A)
    return 3;
if (pointeur == D)
    return 3;
if (pointeur == F)
    return 2;
if (pointeur == G)
    return 4;
if (pointeur == H)
    return 4;
if (pointeur == J)
    return 3;
if (pointeur == K)
    return 5;
if (pointeur == L)
    return 4;
if (pointeur == M)
    return 5;

}

Ответы [ 5 ]

3 голосов
/ 01 сентября 2011

temp и debut являются пустыми указателями - поскольку void не имеет определенного размера, оператор индексации массива нельзя использовать для указателей этого типа (насколько велик объект, на который указывает void*?) .

1 голос
/ 01 сентября 2011

Вы не можете использовать void* в арифметике ... так что, в основном, когда вы говорите debut[k], это требует операции сложения со значением указателя, что вы не можете сделать ... вы будете иметьпреобразовать это значение указателя в другой тип указателя, прежде чем вы сможете добавить к нему.

Если честно, тип debut должен быть на самом деле void**, так как он указывает на массив A, которыймассив указателей на указатели.Вы можете индексировать в этом.Поэтому измените ваше объявление следующим образом:

void ** debut = A;

Теперь оно может фактически добавить к debut, поскольку оно знает, что значение, на которое оно указывает, является указателем и, следовательно, может быть увеличено на размеруказатель на вашей платформе.Вы по-прежнему не сможете совершать вызовы, например temp[k], поскольку теперь temp относится к типу void*, но по крайней мере debut[k] будет действительным.

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

1 голос
/ 01 сентября 2011

debut - указатель void, и указатели void нельзя разыменовать, не приведя их к другому типу указателя.Оператор индекса массива [] эффективно разыменовывает базовый указатель, добавляя смещение.

0 голосов
/ 01 сентября 2011

Я не верю, что вы можете индексировать в пустоту *, так как как компилятор узнает, сколько байтов нужно перейти (то есть индекс). Возможно, вам придется сначала выполнить приведение, затем индексировать.

0 голосов
/ 01 сентября 2011

debut - указатель типа void *. Вы не можете использовать оператор [] с указателем типа void *. Это незаконно в C. Что это должно означать в вашем коде?

Ваш компилятор, очевидно, позволяет использовать [] с debut как расширение, специфичное для компилятора (это, тем не менее, недопустимо в C). Однако результатом debut[k] является «lvalue» типа void. Вы не можете прочитать void. Вы не можете присвоить void чему-либо. Это просто не имеет никакого смысла. Что вы пытались сказать, пытаясь прочитать «значение» debut[k]?


Учитывая ваш комментарий, очевидно, что вам нужно debut объявлено как

void **debut;

Примечание две звездочки.

Опять же, если вы хотите получить доступ к элементам массива void * A[3] через независимый указатель debut, указатель debut должен быть объявлен и инициализирован следующим образом

void **debut = A;

Таким образом, доступ к debut[k] на самом деле приведет к A[k].

То же самое относится к fin. Фактически, ваша программа содержит множество независимых примеров этой ошибки (см. Также параметры функции), хотя некоторые из них более «прощающие», чем debut[k].

P.S. Ваш цикл будет повторяться бесконечно, так как вы никогда не измените ни debut, ни fin.

...