#c
#c
Вопрос:
Я пытаюсь написать программу коллоидного моделирования на C, и я столкнулся с любопытной проблемой, которую я не знаю, как решить — я сократил код до минимума, где он показывает ошибку того же типа. (Заранее прошу прощения за длину кода …)
/** main.c **/
#include <stdio.h>
/** typedefs **/
typedef struct { double x, y, z; } point;
typedef struct {
double radius;
point pos, potential, velocity;
} particle;
typedef struct {
int num; // size of particle array
particle *particles;
} trough;
typedef struct { trough trough; } experiment;
void printPoint(point a) { printf("%f, %f, %fn", a.x, a.y, a.z); }
/** initializations **/
point initPoint(double x, double y, double z) {
point new_point = { .x = x, .y = y, .z = z };
return(new_point);
}
particle initParticle(double radius, point pos, point potential, point velocity) {
particle new_particle = { .radius = radius, .pos = pos, .potential = potential, .velocity = velocity };
return(new_particle);
}
trough initTrough(particle particles[]) {
int num = sizeof(particles) / sizeof(int) 1;
trough new_trough = { .num = num, .particles = particles };
return(new_trough);
}
experiment initExperiment(trough in_trough) {
experiment new_experiment = { .trough = in_trough };
return(new_experiment);
}
/** probs **/
experiment newExperiment() {
particle new_part1 = initParticle(1, initPoint(0, 4, 0), initPoint(0, 0, 0), initPoint(0, 0, 0));
particle new_part2 = initParticle(1, initPoint(4, 4, 0), initPoint(0, 0, 0), initPoint(0, 0, 0));
printPoint(new_part1.pos);
printPoint(new_part2.pos);
particle particles[2] = { new_part1, new_part2 };
trough new_trough = initTrough(particles);
printPoint(new_trough.particles[0].pos);
printPoint(new_trough.particles[1].pos);
return(initExperiment(new_trough));
}
int main(int argc, char *argv[]) {
experiment experiment = newExperiment();
printPoint(experiment.trough.particles[0].pos);
printPoint(experiment.trough.particles[1].pos);
return(0);
}
Я компилирую код: gcc -lm -std=c99 -Wall main.c
и запускаю его: ./a.out
и получаю следующий вывод:
$ ./a.out
0.000000, 4.000000, 0.000000
4.000000, 4.000000, 0.000000
0.000000, 4.000000, 0.000000
4.000000, 4.000000, 0.000000
0.000000, 4.000000, 0.000000
0.000000, 4.000000, 0.000000
Проблема заключается в последней строке вывода, где я пытался найти значения x, y, z точки в массиве частиц — все, что я сделал в коде, это напечатал значения в разных точках, и поэтому значения не должны меняться, но они есть, иЯ совершенно не понимаю, почему это так. Связано ли это со ссылкой на массив по индексу? Любая помощь будет принята с благодарностью.
Комментарии:
1. Кроме того,
sizeof(particles)
не делает того, что вы думаете, потому что параметры функции никогда не имеют типа массива. Несмотря на то, что вы написалиtrough initTrough(particle particles[])
, типparticles
isparticle*
. Объявление, вероятно, должно бытьtrough initTrough(int num, const particle* particles)
.
Ответ №1:
Вы забыли выделить частицы в своей корыто-структуре. Есть несколько способов сделать это. В вашем примере исправление заключается в том, чтобы сделать particles массивом из двух элементов:
typedef struct {
int num; // size of particle array
particle particles[2];
};
вместо particals-pointer (который указывает «нигде» в вашем примере).
Конечно, вам нужно выбрать правильную структуру данных для вашего приложения. Списки, массивы определенного размера или выделенные массивы и т. Д.
Ответ №2:
Тип trough
не содержит массива particle
s. Он содержит указатель, который может указывать на массив particle
s. Вы инициализировали его, чтобы указать на локальный массив функции, объявленный в newExperiment()
.
Но когда функция newExperiment
завершается, время жизни массива заканчивается, и попытка снова использовать этот висячий указатель main
вызывает неопределенное поведение.
Если количество частиц известно как максимальное во время компиляции, вы можете изменить элемент указателя на элемент массива, как показал @Patrick B. Если нет, вам нужно будет использовать malloc
и free
, чтобы убедиться, что элемент указателя указывает на память, которая будет оставаться действительной до тех пор, пока вам это нужно.