В чем проблема?
В InitField()
параметр Feld
указан как указатель на указатель на TFeld.
*Feld
, следовательно, указатель на TFeld
. Он правильно инициализируется свежей выделенной областью памяти правильного размера.
Затем вы звоните test()
проходя *Feld
в качестве аргумента. К сожалению, вы также вызываете аргумент Feld
, так что тип этой переменной отличается и может вызвать некоторые головные боли. Но это не проблема. Функция тестирования должна делать то, что ожидаете.
Когда вы вернулись в InitField()
вы попробуете получить доступ к элементам, которые вы инициализированы:
Feld[i]->Schiff_Versunken = ... //ouch !!!
Это принимает указатель на указатель и доступ к указатель-ю в этой таблице. Но поскольку ваш указатель на указатель - это просто poitner, а не массив, вы возвращаете указатель, который полностью поврежден. Затем вы разыгрываете этот указатель-поводырь с ->
, делая вид, что он указывает на TFeld
. Когда вы затем назначаете ценность этому жульническому адресу, у вас есть неопределенное поведение (может быть segfault, может быть заморожено, может быть что угодно).
Edit: дополнительная информация по указателю разыменования:
Операторы *
->
и []
имеют order of precendence, которые вы должны привыкнуть. Давайте посмотрим на TFeld **Feld
:
*Feld[i]
тот же, что *(Feld[i])
, потому что первый []
, а затем применяется только *
. Кстати, идя дальше и применяя правила арифметики указателей, это то же самое, что и *(*(Feld+i))
. В любом случае, это не то, что вам нужно
*Feld[i].xxx
такое же, как *((Feld[i]).xxx)
, потому что .
имеет более высокий приоритет, чем *
.Это не будет компилироваться, так Feld[i]
не тип TFeld
Feld[i]->xxx
таким же, как (Feld[i])->xxx
(потому что []
и ->
имеют одинаковый приоритет, но когда оба появляются они применяются слева направо). Это то же самое, что и (*(Feld[i])).xxx
. И еще не то, что вы хотите.
Но давайте визуализируем, чтобы понять влияние применения разыменования в другом порядке. Наверху то, что вам нужно. Ботом это то, что вам следует избегать:
Как решить?
Я предлагаю изменить закомментирована часть в:
for (i=0;i<E.Groesse_X*E.Groesse_Y;i++)
{
(*Feld)[i].Schiff_Versunken = false;
(*Feld)[i].Schiff_Versunken = false;
(*Feld)[i].Ueberprueft = false;
}
Или, если вам не нравятся звезды и partenheses:
Feld[0][i].Schiff_Versunken = false;
Feld[0][i].Schiff_Versunken = false;
Feld[0][i].Ueberprueft = false;
DOUBLE indirections являются ВСЕГДА немного сложнее. Всякий раз, когда вы сомневаетесь, добавьте некоторые круглые скобки.
Заключительное слово: я предположил, что здесь InitField()
был вызван с действительным указателем на указатель на TFeld
, так что *Feld
бы без точки сомнения в указатель на TFeld
. Если это будет так, указатель на выделение памяти может быть записан в любом месте в памяти, что приведет к повторному повреждению памяти. Если вы сомневаетесь, сделайте для редактирования свой вопрос, показывающий код вызова, чтобы я мог проверить.
Где вы написали 'Feld [i] ->' вы, вероятно, имели в виду '(* Feld) [i] .' – immibis
В вашем' typedef '' struct' вы можете оставить имя 'TFeld 'в первый раз у вас есть. Как в, 'typedef struct {...} TFeld;' –
bool pointer ?! : D –