У меня есть структура, которую я установил, и указатель на структуру, которая в основном представляет собой массив. Я хочу создать функцию, которая изменяет определенные значения в структуре, но не могу понять, как передать указатель структуры в качестве параметра.
struct deviations {
int switch;
int x;
int y;
};
struct deviations *pdevs = malloc(24 * sizeof(int));
for(int i = 0; i < 8; i++) {
(pdevs + i)->switchez = 1;
(pdevs + i)->x = 0;
(pdevs + i)->y = 0;
}
int top[3] = {0, 1, 2};
int bottom[3] = {5, 6, 7};
int left[3] = {0, 3 ,5};
int right[3] = {2, 4, 7};
for(int i = 0; i < 3; i++) {
(pdevs + top[i])->y = -1;
}
У меня есть несколько (8) for loops, как указано выше, и в каждом из них базовая структура одинакова, за исключением изменения массива ("верх"), lvalue ('y') и rvalue ('-1') в каждом. Я не могу понять, как правильно объявить функцию со структурой / указателем на структуру.
В настоящее время у меня есть около 26 строк кода (8 для повторяющихся циклов), и я почти уверен, что смогу сжать его до аккуратной маленькой функции, если я смогу выяснить, как передать указатель на структуру. Любая помощь приветствуется!
Этот фрагмент является частью более крупной функции / программы, которая определяет, нужно ли проверять окружающие элементы (3 вверху, 3 внизу, по одному с каждой стороны). Я установил структуру с переключателем включения / выключения в зависимости от положения базового элемента и смещения x / y. Я пытаюсь сдвинуть каждую отдельную ячейку на определенную величину + 1 / -1 / или 0 в позиции x или y. И я пытаюсь включить или выключить переключатель в зависимости от определенных условий относительно x или y исходной ячейки. Malloc, вероятно, не нужен, но я не уверен, будет ли этот массив структур использоваться снова позже, если нет, я удалю вызов malloc.
Спасибо!
предложенная вами декларация sizeof определенно подходит, спасибо!
Упс ... Нажал не ту клавишу и отредактировал другой комментарий. Вместо этого вы должны использовать pdevs[top[i]]->y. А еще я предлагаю вам использовать макрос.
Было бы хорошо, если бы вы не пропустили код, который действительно демонстрирует, что вы пытаетесь сделать. Вместо этого вы пытались описать код словами, что сбивает с толку.
И было бы легче понять, если бы вы написали pdevs[top[i]].y = -1
Кроме того, если вам нужно было установить элементы несколько в struct, вы могли бы сделать (например): for (int i = 0; i < 3; ++i) { struct deviations *pdev = &pdevs[top[i]]; pdev->y = -1; pdev->x = -1; pdev->switch = 0; }
@paddy отредактировал и добавил все, кроме повтора для петель, для которых я ищу направление. Буду иметь это в виду, продвигаясь вперед. Благодарность
кроме цикла for я нигде не вижу закрывающих скобок }
Что ж, вы снова пропустили код, поэтому мы не можем определить намерение вашей программы. Это выглядит, как будто вы пытаетесь настроить массив соседей статического размера и их смещение X / Y, например вверху-слева == (-1, -1), вправо == (1,0) и т. д. Зачем для этого нужны циклы или динамическое распределение, вызывает недоумение.
@u__ Он находится в той же строке, что и задание - просто плохое форматирование.
не удержался - пошел дальше и немного отформатировал code
@paddy включает больше контекста. не уверен, достаточно ли этого того, что вы ищете.
спасибо @u__ до сих пор к этому привыкаешь!
Обратите внимание, что struct deviations *pdevs = malloc(24 * sizeof(int)); - неправильный способ выделить массив из 8 структур. Вам нужен struct deviations *pdevs = malloc(8 * sizeof(struct deviations));, т.е. размер структуры НЕ всегда в 3 раза больше размера int. Иногда используется заполнение.





Итак, вам нужна универсальная функция, которая может принимать массив из 3 индексов, член структуры для заполнения и значение.
Массив и значение просты. Для общей обработки члена структуры можно использовать макрос offsetof().
void fill_structs(struct deviations *pdevs, size_t offset, int indexes[3], int value) {
for (int i = 0; i < 3; i++) {
*((int *)((char *)&pdevs[indexes[i]] + offset)) = value;
}
}
Тогда вы называете это так:
fill_structs(pdevs, offsetof(struct deviations, y), top, -1);
offsetof() возвращает смещение в байтах элемента структуры от основания структуры. Итак, в функции вы должны преобразовать адрес элемента массива в char *, чтобы вы могли добавить к нему смещение, а затем преобразовать его в int *, чтобы вы могли разыменовать его и назначить там члену int.
Кстати, вы должны отказаться от привычки использовать такие вещи, как
(pdevs + i) -> x
Если вы используете указатель в качестве основы массива, используйте синтаксис массива:
pdevs[i].x
Таким образом, намного проще определить, что i является индексом массива.
согласен, pdevs [i] - это то, как я должен был его использовать, не знаю, что заставило меня пойти другим путем. Я не знаком с макросами, проведу небольшое исследование и посмотрю, смогу ли я обдумать это, а также это: * ((int *) ((char *) & pdevs [indexes [i]] + offset)) = value; Новичок в C, поэтому пытаюсь разобраться в декларациях this.
Всегда рекомендуется использовать typedefs при работе с structs, например. typedef struct _deviations deviations. Затем вы можете использовать его, как и любые другие типы, например. int, char. size_t, etc без необходимости каждый раз упоминать struct
@Sisir LOL, ранее сегодня я отвечал на вопрос, который использовал typedef, и кто-то еще сказал, что это НЕ хорошая идея, и направил меня к руководству по стилю ядра Linux.
Объявлять typedef struct _deviations* deviations нехорошо, но объявлять typedef struct _deviations deviations абсолютно нормально. Фактически, если вы не будете делать это каждый раз, когда захотите использовать тип, вам придется написать очевидное ключевое слово struct. Однако я согласен с тем, что эта концепция зависит от индивидуального восприятия и ваших текущих руководящих принципов проекта.
Некоторые интересные обсуждения по этой конкретной теме можно найти по ссылкам ниже softwareengineering.stackexchange.com/questions/147545/…stackoverflow.com/questions/516237/…
@Sisir Я знаю о совете "не вводите указатели" и согласен. Это был первый раз, когда мне сказали «вообще не печатать», и я согласен с вами. Но я не собираюсь давать советы тем или иным способом в своих ответах, я просто придерживаюсь того, что сделал OP.
Этот ответ служит исключительно для того, чтобы бросить вызов вашему размышлению о вашем текущем подходе.
Лично, если не задействована какая-то особая логика, я бы просто полностью отказался от циклов и инициализировал вашу структуру таким образом.
const struct deviations devs[8] = {
{ 1, -1, -1 }, // top-left
{ 1, 0, -1 }, // top
{ 1, 1, -1 }, // top-right
{ 1, -1, 0 }, // left
{ 1, 1, 0 }, // right
{ 1, -1, 1 }, // bottom-left
{ 1, 0, 1 }, // bottom
{ 1, 1, 1 } // bottom-right
};
Если вы затем решите, что вам действительно нужно выделять это динамически, вы можете просто скопировать его:
struct deviations *pdevs = malloc(sizeof(devs));
if (pdevs) memcpy(pdevs, devs, sizeof(devs));
Но если вы действительно хотели сгенерировать этот материал в цикле, почему бы не сделать что-то подобное?
int ii = 0;
for(int y = -1; y <= 1; ++y) {
for(int x = -1; x <= 1; ++x) {
if (x == 0 && y == 0) continue;
pdevs[ii].switch = 1;
pdevs[ii].x = x;
pdevs[ii].y = y;
++ii;
}
}
Честно говоря, статический набор массивов, вероятно, является более простым / разумным способом сделать это, у меня действительно было это записано на последней странице моих заметок, а затем я спустился в кроличью нору последние несколько часов и усложнил вещи до миллиардной доли. степень. Спасибо за ясность, думаю, пора прогуляться.
Не стоит беспокоиться. Кстати, я подталкивал вас добавить дополнительные детали к вашему вопросу, потому что подозревал, что он пострадал от XY проблема.
Вы были правы, это точно ... ой.
Вы должны использовать
sizeof(struct deviations)в вызовеmalloc().