Re: Программистские задачки и хитрости
Добавлено: 23 ноя 2019, 17:14
Кстати, а насколько медленней операции с 64-битными числами по сравнению с 32-битными? На 32-битном процессоре.
Статьи, обзоры, цены на станки и комплектующие.
https://cnc-club.ru/forum/
От системы команд зависит. И от реализации этих операций в языках. Конкретно по Cortex'ам не в курсе. Но обычно пересылка-сложение-вычитание раза в 2-3 медленнее. Собственно, проверить нетрудно.MX_Master писал(а):насколько медленней операции с 64-битными числами по сравнению с 32-битными? На 32-битном процессоре.
Давно программизмом не занимался, не могу сходу въехать - не опасно ли вычитание двух беззнаковых? Особенно после переполнения, когда prevtick > curtick. Какой при этом результат будет?Сергей Саныч писал(а):longtick += curtick - prevtick; // Разность текущего и предыдущего отсчетов прибавим к 64-битному счетчику
да, но:MX_Master писал(а): Можно ли (в теории) с помощью аппаратных TX пинов выводить шаги на частотах от 1 до 200000 Гц?
Нормальный результат будетArgon-11 писал(а):Давно программизмом не занимался, не могу сходу въехать - не опасно ли вычитание двух беззнаковых? Особенно после переполнения, когда prevtick > curtick. Какой при этом результат будет?
Код: Выделить всё
0001 (curtick=1)
-
1110 (prevtick=14)
=
0011 (curtick-prevtick=3)
если учесть, что старт-бит обычно это '0', а стоп-бит - '1', то 10101010 превратится в 0101010101, что в общем-то не хужеАлександр Д писал(а): ваша 10101010 превратится в 1101010101 или примерно такое...
Короче, 5-летний перерыв может начисто стереть из памяти правила двоичного вычитанияСергей Саныч писал(а):возьмем покороче, 4-битные.
А ведь множителей частоты может быть и больше. К тому же битрейт тоже настраивается. А для продолжительного постоянного вывода можно прикрутить DMA. Надо попробовать на досуге.Argon-11 писал(а):если учесть, что старт-бит обычно это '0', а стоп-бит - '1', то 10101010 превратится в 0101010101, что в общем-то не хуже
Код: Выделить всё
0000000001 0000000001 0000000001 0000000001 - 4 шага (х1)
0000100001 0000100001 0000100001 0000100001 - 8 шагов (х2)
0001001001 0001001001 0001001001 0001001001 - 12 шагов (х3)
0101010101 0101010101 0101010101 0101010101 - 16 шагов (х4)Оглядываясь на стоимость МК считаю это извратом!MX_Master писал(а):Можно ли (в теории) с помощью аппаратных TX пинов выводить шаги на частотах от 1 до 200000 Гц?
Александр Д не битрейт имел ввиду, а что якобы есть риск получить неровную импульсную последовательность с двумя подряд идущими единицами.MX_Master писал(а):А ведь множителей частоты может быть и больше.
Не пробуй. Делай. Или не делай. Не пробуй. (c) ЙодаMX_Master писал(а):Надо попробовать на досуге.
Перенастройка порта довольно длительная операция во время которой передача невозможна.Argon-11 писал(а):Например, как на лету менять битрейт (поди еще и без прерываний)?
Вот о таких нюансах я и спрашивал (: У аппаратного таймера перенастройка проходит быстро. Лично замерял. А про аппаратные UART'ы таких данных не имею.UAVpilot писал(а):Перенастройка порта довольно длительная операция во время которой передача невозможна.
В какой-то степени, дёргать пины в прерываниях на больших частотах довольно странно. Впрочем, как и юзать DMA в роли счётчика шаговUAVpilot писал(а):Оглядываясь на стоимость МК считаю это извратом!
Насколько помню, PC-шные UART перестраиваются без задержек. А вот у STM только через Disable-Enable.MX_Master писал(а):А про аппаратные UART'ы таких данных не имею.
Наблюдаемое "верное" поведение является частным случаем классического неопределенного поведения. Любые попытки "доказательства корректности" с помощью компилятора в этом случае не имеют смысла. Компилятор имеет право даже не компилировать этот код.UAVpilot писал(а):Ладно, это было легкогугить.
Вот ещё:
Где ошибка и почему работает?Код: Выделить всё
$ cat t.c #include <stdio.h> void print(int a, int b) { printf("print: a=%d, b=%d\n", a), b; } void main(void) { int x = 5, y = 8; print(x, y); } $ make t cc t.c -o t $ ./t print: a=5, b=8 $
7.21.6.3 The printf function
2) The printf function is equivalent to fprintf with the argument stdout interposed before the arguments to printf
PS: Раз тут был упомянут gcc: при отсутствии флага -ffreestanding возвращаемый тип функции main должен быть 'int'.7.21.6.1 The fprintf function
2) The fprintf function writes output to the stream pointed to bystream, under control of the string pointed to by format that specifies how subsequent arguments are converted for output. If there are insufficient arguments for the format, the behavior is undefined. <---
Конкретное поведение в этом примере находится за рамками языка С. Что именно будет напечатано (и будет ли напечатано вообще) зависит от реализации компилятора, флагов, архитектуры и других факторов.В данном случае поведение вполне ожидаемое
Ключевой момент - "при некоторых режимах оптимизации". А при некоторых - нет. Выкинет 'b', как неиспользуемую с т.з. языка переменную и будет прав, т.к. стандарт дает ему на это право:более того, такой-же набор машинных инструкций сгенерит и сам компилятор из "правильного "текста при некоторых режимах оптимизации
Что собственно и делают большинство компиляторов (в т.ч. и gcc 9.2). Какой либо связи между ‘b’ и тем фактом что ‘printf’ что-то там читает из некоторой области памяти (совершенно неважно откуда именно, хоть стек, хоть регистры), которая содержит значение 'b' с точки зрения стандарта нет. Соответственно ни о каких side эффектах говорить не приходится, хотя вызов ‘printf’ обеспечивает их, но только для явно переданных аргументов.5.1.2.3/4
In the abstract machine, all expressions are evaluated as specified by the semantics. An actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no needed side effects are produced.
Код: Выделить всё
#include <stdio.h>
int main()
{
int* a;
int* b;
int c = (int)(a > b);
printf("%d", c);
}Код: Выделить всё
#include <stdio.h>
int main()
{
int i = 5;
i = ++i + ++i;
printf("%d", i);
}Увы нет. Для того, чтобы сделать такое заключение нужны критерии "правильности".И с возвращаемым типом всё правильно
Код: Выделить всё
int plus(int a, int b)
{
return a - b;
}Код: Выделить всё
int plus(int a, int b)
{
return a + b;
}Код: Выделить всё
int minus(int a, int b)
{
return a - b;
}5.1.2.1/1
In a freestanding environment (in which C program execution may take place without any benefit of an operating system), the name and type of the function called at program startup are implementation-defined.
(но с оговоркой что все должно быть задокументировано, см. ниже)5.1.2.1/2
The effect of program termination in a freestanding environment is implementation-defined.
И существует два лагеря людей, которые по разному понимают этот параграф:5.1.2.2.1/1
The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of 'int' and with no parameters:
int main(void) { /*...*/ }
or with two parameters [...]:
int main(int argc, char *argv[]) { /*...*/ }
or equivalent, or in some other implementation-defined manner.
Код: Выделить всё
int main (int argc, char *argv[], char *env[])И у GCC такой документ есть. https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gcc.pdfAn implementation shall be accompanied by a document that defines all implementation-defined and locale-specific characteristics
Ключ ‘-std’ отключает использование extensions. На упомянутой странице 451 в Chapter 6 имеется следующее:By default, GCC provides some extensions to the C language that, on rare occasions conflict with the C standard. See Chapter 6 [Extensions to the C Language Family], page 451. Some features that are part of the C99 standard are accepted as extensions in C90 mode, and some features that are part of the C11 standard are accepted as extensions in C90 and C99 modes. Use of the ‘-std’ options listed above disables these extensions where they conflict with the C standard version selected.
Если попытаться откомпилировать ‘void main(){}’ с ключем '-pedantic', то возникает следующее предупреждение:GNU C provides several language features not found in ISO standard C. (The ‘-pedantic’ option directs GCC to print a warning message if any of these features is used.)
Что это значит? А это значит, что такая language feature not found in ISO standard C.<source>:3:6: warning: return type of 'main' is not 'int' [-Wmain]
Плюс здесь указан тот факт, что по умолчанию используется hosted implementation, а не freestanding (что абсолютно логично).The standard also defines two environments for programs, a freestanding environment, required of all implementations and which may not have library facilities beyond those required of freestanding implementations, where the handling of program startup and termination are implementation-defined; and a hosted environment, which is not required, in which all the library facilities are provided and startup is through a function
int main(void)
or
int main (int, char *[]).
An OS kernel is an example of a program runningin a freestanding environment; a program using the facilities of an operating system is an example of a program running in a hosted environment. GCC aims towards being usable as a conforming freestanding implementation, or as the compiler for a conforming hosted implementation. By default, it acts as the compiler for a hosted implementation.
Т.е. разработчики GCC явно принадлежат к той категории, которая трактуют несколько неоднозначную фразу из параграфа стандарта 5.1.2.2.1/1 как явный запрет 'void' в качестве возвращаемого типа.Warn if the type of main is suspicious. main should be a function with external linkage, returning int, taking either zero arguments, two, or three arguments of appropriate types. This warning is enabled by default in C++ and is enabled by either ‘-Wall’ or ‘-Wpedantic’.