Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Друг Кота
Сообщения: 3092
Зарегистрирован: Пн апр 06, 2015 11:01:53
Откуда: москва, уфа

Сообщение arkhnchul »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3833099#p3833099"]Библиотека оптимизируется под конкретную железку[/uquote]нэ савсэм.
библиотека оптимизируется под архитектуру, в лучшем случае - под семейство. Дальше уже дело конечного программиста сказать компилятору, чего там его конкретная железка не умеет или чего программист сам не хочет. У gcc, например, есть флаг mno-unaligned-access.
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="arkhnchul",url="/forum/viewtopic.php?p=3833449#p3833449"]библиотека оптимизируется под архитектуру,[/uquote]Это я и имел в виду.

[uquote="arkhnchul",url="/forum/viewtopic.php?p=3833449#p3833449"]в лучшем случае - под семейство.[/uquote]В случае ARM - под ядро. Как на уровне компилятора, так и на уровне исходного кода библиотек. При такой конкуренции среди компиляторов под ARM иметь неоптимизированные библиотеки непозволительная роскошь.

[uquote="arkhnchul",url="/forum/viewtopic.php?p=3833449#p3833449"]У gcc, например, есть флаг mno-unaligned-access.[/uquote]Это не панацея. C/C++ так устроен, что можно заставить компилятор сделать невыровненный доступ. Это грубый косяк, но он всё ещё в библиотеках встречается. Ответственный разработчик встретив такое отправит багрепорт автору.

Это мы говорили про тулчейн. Он должен всё об архитектуре чипа знать. Вон, чуть выше код под AVR был

Код: Выделить всё

const __flash char __flash *strs_pwr[] = {};
Убери одну __flash и код кардинально меняется.
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18793
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

VladislavS писал(а):Убери одну __flash и код кардинально меняется
хочется верить, что для ARM код будет вполне рабочим, если предварительно сделать
#define __flash /* */

интересно, каким предопределенным макросом можно отличить arm-gcc от avr-gcc?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="ARV",url="/forum/viewtopic.php?p=3833509#p3833509"]интересно, каким предопределенным макросом можно отличить arm-gcc от avr-gcc?[/uquote]Не только что это ARM и какое конкретно ядро, но ещё и тип и версию компилятора. RTFM.
Пример из моего стартапа

Код: Выделить всё

#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION>=6100100)
  #define __KEIL_CODE__
#elif defined(__GNUC__)
  #define __GCC_CODE__
#elif defined(__ICCARM__)
  #define __IAR_CODE__
#elif defined( __CC_ARM ) || defined(__MICROLIB)
  #error "ARMCC v5 and MICROLIB not supported"
#else
  #error "Can't detect compiler"
#endif
Добавлено after 5 minutes 30 seconds:
[uquote="ARV",url="/forum/viewtopic.php?p=3833509#p3833509"]#define __flash /* */[/uquote]Какой ужас!
Реклама
Эиком - электронные компоненты и радиодетали
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18793
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

VladislavS писал(а):Какой ужас!
поясните, а то ваш эмоциональный возглас несколько напрягает.
правильнее было бы все это переопределить как-то так:

Код: Выделить всё

#if defined(__AVR__)
#define flash __flash
#elif defined(__ARM__)
#define flash
#else
#error ???
#endif
а затем везде по коду применять вместо __flash уже просто flash
я просто поленился писать сразу :)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

помогите, как правильно написать, ни как не соображу. :facepalm:

так не работает
if(mode==условие){
if(month==1 && day==1 && minute%10==9){бегущая строка;} // новый год
if(month==1 && day==20&& minute%10==9){бегущая строка;} // день рож Сережи
if(month==5 && day==1 && minute%10==9){бегущая строка;} // день рож у мамы
if(month==5 && day==9 && minute%10==9){бегущая строка;} // день победы
if(month==6 && day==26&& minute%10==9){бегущая строка;} // день рож Илюши
if(month==8 && day==13&& minute%10==9){бегущая строка;} // день рож Вани
if(hour==21&&minute==55){бегущая строка;} // пора спать

else disp=показывать часы;
}
так все работает
if(mode==условие){
if (month==1 && day==1 && minute%10==9) {бегущая строка;} // новый год
else disp=показывать часы;}
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Применяйте более наглядное форматирование кода, тогда и логика работы программы будет лучше прослеживаться.
Спойлер

Код: Выделить всё

if(mode==условие)
{
  if(month==1 && day==1 && minute%10==9){бегущая строка;} // новый год
  if(month==1 && day==20&& minute%10==9){бегущая строка;} // день рож Сережи
  if(month==5 && day==1 && minute%10==9){бегущая строка;} // день рож у мамы
  if(month==5 && day==9 && minute%10==9){бегущая строка;} // день победы
  if(month==6 && day==26&& minute%10==9){бегущая строка;} // день рож Илюши
  if(month==8 && day==13&& minute%10==9){бегущая строка;} // день рож Вани
  
  if(hour==21&&minute==55)
  	{бегущая строка;} // пора спать
  else 
  	disp=показывать часы;
}

if(mode==условие)
{
  if (month==1 && day==1 && minute%10==9) 
  	{бегущая строка;} // новый год
  else 
  	disp=показывать часы;
}
Так что-ли хотели?
Спойлер

Код: Выделить всё

if(mode==условие)
{
  if(month==1 && day==1 && minute%10==9){бегущая строка;} // новый год
  else if(month==1 && day==20&& minute%10==9){бегущая строка;} // день рож Сережи
  else if(month==5 && day==1 && minute%10==9){бегущая строка;} // день рож у мамы
  else if(month==5 && day==9 && minute%10==9){бегущая строка;} // день победы
  else if(month==6 && day==26&& minute%10==9){бегущая строка;} // день рож Илюши
  else if(month==8 && day==13&& minute%10==9){бегущая строка;} // день рож Вани 
  else if(hour==21&&minute==55){бегущая строка;} // пора спать
  else disp=показывать часы;
}
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

Serzh2000, потому что else if надо, иначе условие "else disp=показывать часы;" будет срабатывать всегда, когда не срабатывает "if(hour==21&&minute==55){бегущая строка;} // пора спать" только, наплевав на остальные.
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

Применяйте более наглядное форматирование кода
if(условие А){
if(условие Б){...;}
if(условие В){...;}
if(условие Г){...;}
else условие Д;
}

нужно что бы было : если условие А верно
проверяем условие Б ,условие В, условие Г ( если одно из них верно бежит строка)
если не одно не верно выполняем else условие Д;

я кавычки не правильно ставлю {} , как правильно?
СпойлерprevDisp=disp; // сохраняем предыдущий дисплей
Serial.print(month);Serial.print(day);Serial.print(minute%10);

if(mode==0){ if(month==1 && day==1 && minute%10==9){disp=dispTabB[second/3];prevTrans=0;} // новый год
if(month==1 && day==20&& minute%10==9){disp=dispTabB[second/3];prevTrans=0;} // день рождения у папы
if(month==5 && day==1 && minute%10==1){disp=dispTabB[second/3];prevTrans=0;} // день рождения у мамы
if(month==5 && day==9 && minute%10==9){disp=dispTabB[second/3];prevTrans=0;} // день победы
if(month==6 && day==26&& minute%10==9){disp=dispTabB[second/3];prevTrans=0;} // день рождения Илюша
if(month==8 && day==13&& minute%10==9){disp=dispTabB[second/3];prevTrans=0;} // день рождения Ваня
if(hour==21&&minute==55) {disp=dispTabB[second/3];prevTrans=0;} // пора спать

else disp=dispTab[second/3];
}
if(mode==1) disp=CLOCKBIG;

if(mode==2){if(hour==21&&minute==55){disp=dispTabMED[second/3];prevTrans=0;}
else disp=dispTab1[second/3];}

if(mode==3) disp=CLOCKMED1;

if(mode==4){ if(month==1 && day==1 && minute%10==9){disp=dispTabANM[second/3];prevTrans=0;} // новый год
if(month==1 && day==20&& minute%10==9){disp=dispTabANM[second/3];prevTrans=0;} // день рождения у папы
if(month==5 && day==1 && minute%10==9 ){disp=dispTabANM[second/3];prevTrans=0;} // день рождения у мамы
if(month==5 && day==9 && minute%10==9){disp=dispTabANM[second/3];prevTrans=0;} // день победы
if(month==6 && day==26&& minute%10==9){disp=dispTabANM[second/3];prevTrans=0;} // день рождения Илюша
if(month==8 && day==13&& minute%10==9){disp=dispTabANM[second/3];prevTrans=0;} // день рождения Ваня
if(hour==21&&minute==55) {disp=dispTabANM[second/3];prevTrans=0;} // пора спать

else disp=dispTab2[second/3];
}
if(mode==5) disp=CLOCK1;

if(mode==6) disp=TEMP;

if(mode==7) disp=CLOCKBIGJMP;

у меня таких условий А несколько...
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

я кавычки не правильно ставлю {} , как правильно?
Вам же написали как надо - else if, чтобы "если ни одно условие не верно".

Код: Выделить всё

if(условие А){
  if(условие Б){...;}
  else if(условие В){...;}
  else if(условие Г){...;}
  else условие Д;
}
PS: Используйте отступы, а на форуме код свой заключайте в тег code, иначен форматирование съезжает.
Опытный кот
Аватара пользователя
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Сообщение Serzh2000 »

:))) :beer: :beer: спасибо ! все получилось :beer: :beer:


спасибо
Грызет канифоль
Аватара пользователя
Сообщения: 275
Зарегистрирован: Вс окт 20, 2019 13:03:56

Сообщение Shuspano »

Написал вот такую убогую програмку:

Код: Выделить всё

#define F_CPU 1000000UL

#define	sclock	PB1
#define sdata	PB2

#define ledpin	PB0

#include <avr/io.h>
#include <util/delay.h>

void setup(void)
	{
	DDRB |= (1 << ledpin)|(1 << sclock)|(1 << sdata);
	}

void hc164send(unsigned char sh_data)
	{
	int i; 
	for (i=0; i<8; i++)
		{
		if (sh_data & 0x80)
			{
			PORTB |= (1 << sdata);
			}
		else
			{
			PORTB &= ~(1 << sdata);
			}
		sh_data = sh_data<<1;
		sh_pulse();
		}
	}
void hc164reset(void)
	{
	hc164send(0x00);
	}

void sh_pulse(void)
	{
	PORTB |= (1 << sclock);
	PORTB &= ~(1 << sclock);
	}

void ledflash(void)
	{
	PORTB |= (1 << ledpin);
	_delay_ms(5);
	PORTB &= ~(1 << ledpin);
	_delay_ms(5);
	}

void main(void)
	{
	setup();
	hc164reset();
	unsigned char j = 0x00; 
	while(1)
		{
		hc164send(j);
		ledflash();
		j++;
		_delay_ms(300);
		}
	}
И пытаюсь ее скомпилять с помощью AVR-GCC. А он такой мне говорит: мол, конфликт типов в подпрограмме sh_pulse().

Код: Выделить всё

D:\comp\avr8-gnu-toolchain\bin>avr-gcc -Os -mmcu=atmega48 -o d:\avr\hc164.elf d:
\avr\hc164.c
d:\avr\hc164.c:38:6: warning: conflicting types for 'sh_pulse' [enabled by defau
lt]
 void sh_pulse(void)
      ^
d:\avr\hc164.c:30:3: note: previous implicit declaration of 'sh_pulse' was here
   sh_pulse();
   ^
хотя, она ничего не принимает, и ничего не возвращает. Но если заменить void на int, то становится все хорошо. На другие void почему-то не ругается
Почему компилятору не понравилась именно эта подпрограмма?
И еще вопрос: пытался делать это под линуксом (debian 10 x64), там AVR-GCC (установленный через APT) выдает типа:

Код: Выделить всё

/mnt/ntfs_d/avr/hc164.c:13:2: error: 'DDRB' undeclared (first use in this function)
  DDRB |= (1 << ledpin)|(1 << sclock)|(1 << sdata);
  ^
/mnt/ntfs_d/avr/hc164.c:13:2: note: each undeclared identifier is reported only once for
each function it appears in
avr-libs установлен. Файлы *.h физически присутствуют, проверил. Другие файлы (в. т ч с этим DDRB) компилирует. В интернете - пространные рассуждения на 20 страниц по английски.
Друг Кота
Аватара пользователя
Сообщения: 4906
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Это потому что sh_pulse вызывается в коде раньше, чем объявляется - отсюда и проблема implicit declaration.

А необъявленные функции вроде как считаются по умолчанию возвращающими int, отсюда и "починка" помогает.

Либо выстраивайте последовательность функций так, чтобы "верхние" никогда не использовали "нижние", либо, что правильнее, для каждой функции в начале файла их дополнительно объявляйте. В идеале - как static, если они не вызываются из других модулей.
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

[uquote="Shuspano",url="/forum/viewtopic.php?p=3835922#p3835922"]d:\avr\hc164.c:30:3: note: previous implicit declaration of 'sh_pulse' was here
sh_pulse();
^[/uquote]
Уже ответили, но если не понятно, после #include'ов напишите строку void sh_pulse(void); именно с ; в конце, без самого тела функции и заработает всё. Кстати void в скобках можно не писать везде. void sh_pulse()

И еще вопрос: пытался делать это под линуксом (debian 10 x64), там AVR-GCC (установленный через APT) выдает типа:
Скорее всего в опциях компиляции не указали модель МК ключиком -mmcu
Грызет канифоль
Аватара пользователя
Сообщения: 275
Зарегистрирован: Вс окт 20, 2019 13:03:56

Сообщение Shuspano »

[uquote="WiseLord",url="/forum/viewtopic.php?p=3835924#p3835924"]Это потому что sh_pulse вызывается в коде раньше, чем объявляется.[/uquote]
NStorm писал(а):Кстати void в скобках можно не писать везде. void sh_pulse()
Спасибо, буду знать.
Когда-то достаточно давно, пытался ковырятся с Borland C 3.1, помню он очень ревностно относился к синтаксису.
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

Ну нынче если вы определяете (не путать с объявлением, о котором я выше написал) функцию, то f() { ... } = f(void) { ... }. А вот с объявлением ( f(); ) могут быть нюансы, если потом определение не void. Я что-то сразу об этом не подумал. Если привыкли писать f(void) то и фиг с ним, проблема не в этом )
Друг Кота
Аватара пользователя
Сообщения: 7383
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

Подскажите как сделать. Тоже рисую велосипед меню. И у меня есть такая структура:

Код: Выделить всё

typedef struct {
	unsigned char todisplay[16];
				int *variable;
		 datatype_t datatype;
} menuitem_t;
И вот мне захотелось, чтобы int* variable иногда являлся адресом void функции без параметров, которую я хочу запустить на выполнение.
как написать функцию, которой если передать int *variable, вызвала бы на выполнение функцию по адресу этой variable?

Код: Выделить всё

void FreeRun(void);

menuitem_t menu[] = {
...
{"Free Run", (int*)FreeRun, execute},
...
}
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

как написать функцию, которой если передать int *variable, вызвала бы на выполнение функцию по адресу этой variable?
Можно запустить на выполнение, например, так:

void Test(void)
{

};

menuitem_t menuitem;
menuitem.variable=(int*)Test;

typedef void (*func_ptr)(void);

((func_ptr)menuitem.variable)();
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 7383
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

Написал так:

Код: Выделить всё

void do_execute(int* addr) {
	void (*Task)(void);
	Task = (void (*)(void))addr;
	(*Task)();
}
Вррроде работает... сейчас попробую через typedef.

О, так даже проще! Спасибо.
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
Друг Кота
Аватара пользователя
Сообщения: 4906
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Вот такой пример:
Спойлер

Код: Выделить всё

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

typedef enum {
    var_int,
    var_char,
    execute,
} datatype_t;

typedef struct {
    unsigned char todisplay[16];
    void *variable;
    datatype_t datatype;
} menuitem_t;

void FreeRun(void)
{
    printf("Hello FreeRun\n");
}

int height = 3;
char hour = 10;

typedef enum {
    HEIGHT,
    FREE_RUN,
    HOUR,
} menuidx_t;

menuitem_t menu[] = {
    [HEIGHT]    = {"Height", &height, var_int},
    [FREE_RUN]  = {"Free Run", FreeRun, execute},
    [HOUR]      = {"Hour", &hour, var_char},
};

typedef void (*execute_func)(void);


void handleMenu(menuidx_t idx)
{
    switch (menu[idx].datatype) {
    case var_int: {
        int *var = (int *)(menu[idx].variable);
        (*var)++;
    }
    break;
    case var_char: {
        char *var = (char *)(menu[idx].variable);
        (*var)--;
    }
    break;
    case execute: {
        execute_func func = (execute_func)(menu[idx].variable);
        func();
    }
        break;
    }
}

int main()
{
    printf("----Before:\n");
    printf("Height: %d\n", height);
    printf("Hour: %d\n", hour);

    handleMenu(HEIGHT);
    handleMenu(FREE_RUN);
    handleMenu(HOUR);

    printf("----After:\n");
    printf("Height: %d\n", height);
    printf("Hour: %d\n", hour);

    return 0;
}
Выводит:
Спойлер

Код: Выделить всё

----Before:
Height: 3
Hour: 10
Hello FreeRun
----After:
Height: 4
Hour: 9
Контактная информация:
Ответить

Вернуться в «Разные вопросы по МК»