Я пытаюсь сделать две переменные структуры одинаковыми для всего массива структур. Мне интересно, как бы вы это сделали, поскольку я не могу найти ни малейшего понятия о том, что я хочу сделать. Я использую язык C Вот определение структуры.
struct exp
{
uint8_t ReadA[2];
uint8_t ReadB[2];
GPIO_TypeDef* port;
uint16_t pinmask;
uint8_t Arec[1];
uint8_t Brec[1];
} exps[2];
}
Я попробовал несколько вариантов.
exps.ReadA = {0x41,0x12};
exps[].ReadA[] = {0x41,0x12};
exps[].ReadA = {0x41,0x12};
exps.ReadA[] = {0x41,0x12};
exps->ReadA = {0x41,0x12};
exps[]->ReadA[] = {0x41,0x12};
exps[]->ReadA[] = {0x41,0x12};
exps[]->ReadA[] = {0x41,0x12};
Ни один из них не работает, и они выдают мне ошибки, которые something is expected before token (],{,;)
Единственный обходной путь, который я нашел, - это написать фрагмент данных за фрагментом.
Это то, что я имею в виду:
exps[0].ReadA[0]=0x41;
exps[0].ReadA[1]=0x12;
exps[0].ReadB[0]=0x41;
exps[0].ReadB[1]=0x13;
exps[1].ReadB[0]=0x41;
exps[1].ReadB[1]=0x12;
exps[1].ReadB[0]=0x41;
exps[1].ReadB[1]=0x13;
Также мне нужно увеличить этот массив структур (от 15 до 20 структур).
Я думал об этом, но мне нужно больше переменных для структуры. ReadA и ReadB — это команды для расширителя ввода-вывода, который я использую. Мне нужно 15 или более команд на расширитель ввода-вывода, и это будет означать несколько сложный цикл for. Кроме того, я не хочу использовать для этого глобальные переменные, я боюсь опечатки в моем коде и перегорания чипов и флэш-памяти микроконтроллера.
Что ж, вам придется сделать цикл (или что-то подобное). Этой магической команды не существует.
Вы спрашиваете об установке значений во время компиляции или эта операция должна выполняться (неоднократно) во время выполнения программы?
пожалуйста, опубликуйте что-нибудь, что можно было бы скомпилировать, завершить. А как насчет GPIO_TypeDef
?
@arfneto GPIO_TypeDef — это предопределенный тип данных STM32, который я использую. Он указывает на назначенный мной порт GPIO.
@Fe2O3 во время компиляции. Если настало время компиляции программы, я бы хотел, чтобы эти значения во время компиляции не работали.
В C вы не можете назначать целые массивы во время выполнения. Возможные варианты:
memcpy
значения в элемент массива.Возможно, комбинация memcpy
, именованного #define
и «составного литерала» (временного объекта) подойдет для минимизации повторения кода?
#define READ_A_STUFF 0x41,0x12
#define READ_B_STUFF 0x41,0x13
for(size_t i=0; i<n; i++)
{
memcpy(&exps[i].ReadA, (uint8_t [2]){ READ_A_STUFF }, 2);
memcpy(&exps[i].ReadB, (uint8_t [2]){ READ_B_STUFF }, 2);
}
В противном случае «вся структура сразу», также использующая составную литеральную структуру, будет выглядеть так:
for(size_t i=0; i<n; i++)
{
exps[i] = (struct exp) {
.ReadA = {0x41, 0x12},
.ReadB = {0x41, 0x13},
.port = ...
...
};
}
Но это всего лишь 32-битная область. Вы можете использовать объединение и присваивать любые значения. Никакого повторения, никакого вызова функции
@arfneto Объединение здесь не имеет очевидной цели, и memcpy
вряд ли является обычным вызовом функции, если вы беспокоитесь о производительности.
Вы можете назначить весь массив только во время компиляции (во время объявления массива). Но вы не можете назначить весь массив во время выполнения.
В следующем коде присвоение a1
допустимо, но присвоение a2
недопустимо.
void main()
{
/* this is ok. we can assign whole array in compile time. */
char a1[2] = { 1, 2 };
char a2[2];
/* this is error. we can't assign whole array at runtime */
//a[2] = { 1, 2 };
}
Во время компиляции вам даже не нужно определять размер массива. Поскольку это очевидно из контекста (char a3[] = { 1, 2 }
).
Но это всего лишь 32-битная область. Вы можете использовать объединение и присваивать любые значения. Никакого повторения, никакого вызова функции
Я предполагаю обобщенное решение. Вы можете использовать union
для простых случаев и назначать 4 или 8 int8_t
одновременно. Но сохраняйте свой код в здравом уме.
Ну просто смотрю
struct exp
{
uint8_t ReadA[2];
uint8_t ReadB[2];
GPIO_TypeDef* port;
uint16_t pinmask;
uint8_t Arec[1];
uint8_t Brec[1];
} exps[2];
}
вы видите два }
и только один {
, поэтому неудивительно, что компилятор не воспринимает это как действительный код. Какого типа будет exps[]
? Или участники exp
?
Если ваш struct
именно такой, каким кажется, то для каждой структуры в массиве есть 4-байтовый заголовок.
#include <stdint.h>
#include <stdio.h>
#define Op4112 0x4112
#define Op4113 0x4113
typedef uint32_t GPIO_TypeDef; // any
typedef struct
{
union
{
uint8_t byte[4];
uint16_t word[2];
uint32_t dword;
} Header;
GPIO_TypeDef* port;
uint16_t pinmask;
uint8_t Arec[1];
uint8_t Brec[1];
} Op;
typedef struct
{
Op op[20];
} Set;
int dump_value(const Op*, const char*);
int main(void)
{
uint64_t Iam64 = 0x0102030405060708;
uint8_t* byte = (uint8_t*)&Iam64;
printf(" A 64-bit value: 0x");
for (size_t i = 0; i < 8; i += 1)
printf("%02x", (int)byte[i]);
printf("\n");
Set my_set;
my_set.op[0].Header.dword = 0x01020304;
dump_value(
&my_set.op[0], "\nUsing 0x01020304 to test ");
// set values for op[19] 1st word as 16-bit values
my_set.op[19].Header.word[0] = Op4112;
// set values for op[19] 2nd word as 8-bit values
my_set.op[19].Header.byte[2] = 0x41;
my_set.op[19].Header.byte[3] = 0x13;
dump_value(
&my_set.op[19],
"\nChanging values for header in op[19] ");
return 0;
}
int dump_value(const Op* op, const char* msg)
{
if (msg != NULL) printf("%s", msg);
printf(
"Buffer:\n\
32-bit dword = [ 0x%08x ]\n\
As 16-bit words = [ 0x%04X, 0x%04X ]\n\
As 8-bit bytes = [ 0x%02X, 0x%02X, 0x%02X, 0x%02X ]\n ",
op->Header.dword, op->Header.word[0],
op->Header.word[1], op->Header.byte[0],
op->Header.byte[1], op->Header.byte[2],
op->Header.byte[3]);
return 0;
}
A 64-bit value: 0x0807060504030201
Using 0x01020304 to test Buffer:
32-bit dword = [ 0x01020304 ]
As 16-bit words = [ 0x0304, 0x0102 ]
As 8-bit bytes = [ 0x04, 0x03, 0x02, 0x01 ]
Changing values for header in op[19] Buffer:
32-bit dword = [ 0x41134112 ]
As 16-bit words = [ 0x4112, 0x4113 ]
As 8-bit bytes = [ 0x12, 0x41, 0x13, 0x41 ]
Конечно, как сказано в комментариях, вы не можете присваивать значения целым массивам во время выполнения, но мы говорим здесь о простом 32-битном объекте, и вы наверняка можете присваивать ему значения.
См. приведенный выше пример, в котором объединение используется для перераспределения области как 32, 2x16 или 4x8 байт, чтобы иметь возможность присваивать значения любому внутреннему байту.
Это не эквивалентный код тому, что получил ОП. Теперь вы встроили зависимость от порядка байтов, которой не было в исходном коде. И вместе с этим возможны дополнительные ошибки, а также невозможность переносимости.
Извините, что не ответил, у меня были другие дела, и я начал делать приложение для проекта. struct extra } в объявлении структуры была БОЛЬШОЙ опечаткой при вводе вопроса. Просмотрев несколько раз мой код и прочитав то, что я написал здесь, вы сможете лучше сказать, чего я хочу. Я хочу, чтобы в структуре были переменные (команды), одинаковые для всего массива структур. В исходном посте вы могли видеть, как я это пробовал, и это выдало ошибку. Команды должны быть одинаковыми. Теперь я изучаю вложенные структуры, внутренняя структура которых будет структурой команд.
А позже в коде я добавлял переменные к этой внутренней структуре, а затем назначал их всему массиву структур. Извините за долгое время ожидания.
После того, как его спросили, ОП сообщил, что они ищут решение «во время компиляции».
Этот урезанный код должен указать путь.
#include <stdio.h>
int main( void ) {
struct exp {
uint8_t A[2];
uint8_t B[2];
/* additional struct members are initialised to 0 or NULL */
} e[ 3 ] = { // NB: 3 specified
{ { 0x41, 0x12 }, { 0x41, 0x13 } }, // <== e[0]
{ { 0x41, 0x12 }, { 0x41, 0x13 } }, // <== e[1]
/* e[2] initial values default to 0 */
};
printf( "e[0] vals: %02X %02X %02X %02X\n", e[0].A[0], e[0].A[1], e[0].B[0], e[0].B[1] );
printf( "e[1] vals: %02X %02X %02X %02X\n", e[1].A[0], e[1].A[1], e[1].B[0], e[1].B[1] );
printf( "e[2] vals: %02X %02X %02X %02X\n", e[2].A[0], e[2].A[1], e[2].B[0], e[2].B[1] );
return 0;
}
Выход:
e[0] vals: 41 12 41 13
e[1] vals: 41 12 41 13
e[2] vals: 00 00 00 00
Укажите подходящее значение (с соответствующим синтаксисом) для каждого элемента массива и/или члена struct
, который нужно инициализировать. Неуказанные значения будут установлены компилятором на 0
(или NULL
). Не существует подходящего синтаксиса «дублировать эти значения x раз». (Пожалуйста, не пишите вложенные макросы, которые пытаются добиться этого. Держитесь подальше от сил тьмы.)
спасибо за совет, у меня это работает.
просто переберите массив и установите поле каждого члена индивидуально.