Перейти к содержанию
    

Константа, как параметр функции

Добрый день, уважаемые.

void Func (char* str)

Func ("Hello, World!")

Имеем, для примера, такой вот заголовок функции и пример обращения. В Func передаётся указатель на строку, строку компилятор помещает во flash и это хорошо!

Необходимо сделать,  для примера:

typedef struct {
 int A;
 int B;
 float C;
} Data;

void Func (Data* data) ?

Func ({12, 10, 145.78}) ?

Т.е. непонятно, как описать функцию, чтобы компилятор разместил структуру во flash и передал её указатель в функцию, как это было со строкой.

Со строкой же это работает...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

typedef struct {
 int A;
 int B;
 float C;
} Data;

const Data data = { 12, 10, 145.78 };

....

void Func (Data* data) 
{
....
}



.....

Func (&data);

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

23 минуты назад, pyroman сказал:
void Func (char* str)

Func ("Hello, World!")

Имеем, для примера, такой вот заголовок функции и пример обращения. В Func передаётся указатель на строку, строку компилятор помещает во flash и это хорошо!

И это плохо. Так как функция описана как принимающая указатель на char *, а значит - предполагается, что она будет менять содержимое str. А по факту передаёте ей указатель на char const *. Что чревато вылетом в исключение.

Или крестик снимите или трусы наденьте Или функцию объявляйте как void Func(char const *str) или не передавайте ей константы в аргументе.

13 минут назад, Forger сказал:
const Data data = { 12, 10, 145.78 };

....

void Func (Data* data) 
{
....
}



.....

Func (&data);

И вам - аналогично.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

37 minutes ago, jcxz said:

Или функцию объявляйте как void Func(char const *str) или не передавайте ей константы в аргумент

Спасибо, но не суть.

Вопром в том, как же объявить константную структуру именно, как аргумент/в аргументе функции?

Это для чего, собственно: имеем множество вызовов функции с разными исходными данными, которые константы, но разные. Чтобы удобнее было читать исходник, сразу видеть, что передаётся в функцию, как с Func ("Hello, World!")

Изменено пользователем pyroman

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

32 minutes ago, jcxz said:

Что чревато вылетом в исключение.

В данном случае специально убрано все "лишнее", иначе это еще больше запутает новичка ))

5 minutes ago, pyroman said:

как же объявить константную структуру именно, как аргумент/в аргументе функции?

Внутри вызова функции в си - никак.

В плюсах еще можно по-изголяться с шаблонами, но вам оно надо? 😉  

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

#define Func2(...)		do { const Data t = __VA_ARGS__; Func(&t); } while (0)

typedef struct {

	int	A;
	int	B;
	float	C;
}
Data;

void Func(Data *d)
{
	printf("%i %i %f\n", d->A, d->B, d->C);
}

int main()
{
	Func2({3,4,6.7});
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

17 минут назад, pyroman сказал:

Вопром в том, как же объявить константную структуру именно, как аргумент/в аргументе функции?

Это для чего, собственно: имеем множество вызовов функции с разными исходными данными, которые константы, но разные. Чтобы удобнее было читать исходник, сразу видеть, что передаётся в функцию, как с Func ("Hello, World!")

Воспользуйтесь макросами:

struct Qqq { int a, b; };
void Func(Qqq const *pq)
{
  ...
}

#define FuncConst(...) {            \
  static Qqq const t = __VA_ARGS__; \
  Func(&t);                         \
}

...

  FuncConst({1, 2});
  FuncConst({2, 3});
12 минут назад, amaora сказал:
#define Func2(...)		do { const Data t = __VA_ARGS__; Func(&t); } while (0)

typedef struct {

	int	A;
	int	B;
	float	C;
}
Data;

void Func(Data *d)
{
	printf("%i %i %f\n", d->A, d->B, d->C);
}

int main()
{
	Func2({3,4,6.7});
}

 

То, что do { .. } while (0) использовали - хорошо. А то, что про static (в const Data t) и про const (в аргументе функции) забыли - плохо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если компилятор gcc (или совместимый), то можно использовать его расширение:

#define CONST(Type, ...) ({static const Type var = {__VA_ARGS__}; &var})
                          
func(CONST(MyStruct, 1, 2, 3, 4))

Преимущество - один макрос на любое количество функций и типов параметров, недостаток - только gcc (и примкнувшие к нему)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо всем, макрос работает, проверил.

Ещё вопрос. Почему макрос не работает должным образом (компилятор передаёт структуру в функцию через стек) без ключевого слова static? Со static полный порядок - имеем указатель на структуру во flash.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, pyroman сказал:

Ещё вопрос. Почему макрос не работает должным образом (компилятор передаёт структуру в функцию через стек) без ключевого слова static? Со static полный порядок - имеем указатель на структуру во flash.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

#define fillRect(x0, y0, x1, y1, flags) fillRect_(y0<<8 | x0, y1<<8 | x1, flags)

void fillRect_(unsigned long param0, unsigned long param1, unsigned long flags)

fillRect(0, 0, 127, 63, DRAW_OR);

По итогу, применил вот так вот.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, pyroman said:

По итогу, применил вот так вот.

И где тут 'структура во FLASH' с которой всё начиналось?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, xvr said:

И где тут 'структура во FLASH' с которой всё начиналось?

 

typedef struct {
  signed long x0;
  signed long y0;
  signed long x1;
  signed long y1;
  unsigned long flags;
} Rect;

#define fillRect(...) { \
  static const Rect t = __VA_ARGS__; \
  fillRect_(&t) \
}

void fillRect_(Rect* param0)
{
}

fillRect({0, 0, 127, 63, DRAW_OR})

Вариант Б 🙂

Изменено пользователем pyroman

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, pyroman said:

Вариант Б 🙂

если исправить ошибки, то вот так собирается:

typedef struct {
  signed long x0;
  signed long y0;
  signed long x1;
  signed long y1;
  unsigned long flags;
} Rect;


void fillRect_(const Rect* param0)
{
}

#define fillRect(...) { \
  static const Rect t = __VA_ARGS__; \
  fillRect_(&t); \
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А в чем сопсна проблема то? Пишите структуру, объявляете переменную типа структуры с квалификатором const. Далее - забота линкера. Если его скрипт написан верно, то в нем будет секция .rodata, которая опознает все const и кладет туда, куда в ней сказано, то есть в область FLASH, которая, в свою очередь, так же должна быть верно описана и в ней указаны адрес начала флеша. 

969990232_2023-05-07214648.png.fdd32b20732f37456851d8d384ade1f3.png

 

И квалификатор const в параметре функции защищает на уровне компиляции от изменений константного значения, хранящегося во флеще:

2058134454_2023-05-07214945.png.0493ffd6e92f6597588c13ec9888d4ae.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...