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

Только что, Integro сказал:

минус такого исполнения только один, выглядит криво, не так красиво как это мог сделать препроцессор

Именно:smile:

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


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

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

Где я такое утверждал (что строка не нужна)??? :shok: 

Я сказал, что ТСу нужна (в данном конкретном месте) не сама строка, а некие производные от неё данные.

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

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


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

В 19.04.2019 в 14:31, Arlleex сказал:

2. Теперь я хотел также на этапе препроцессирования вот эти самые BUILD_DAY, BUILD_MONTH и BUILD_YEAR преобразовать в строку Си ("..." которая) с помощью директивы #.

Какое-то время назад тоже потратил несколько часов на поиск решения подобной задачи "преобразовать макрос в строку". Ответ получился отрицательный - средствами языка Си это невозможно. Вот, в справке по GCC есть такая фраза: "There is no way to convert a macro argument into a character constant."

И проблема в том, что как уже сказали выше, препроцессор только осуществляет макрозамену одних выражений на другие. А все вычисления потом проводит уже компилятор. А как только препроцессор превращает выражение в строку, то компилятор согласно правилам это выражение больше не трогает.

В результате имеем:

  • если результатом макроподстановки была константа (уже в явном виде), то её можно преобразовать в строку,
  • если же результатом макроподстановки было выражение, то его тоже можно превратить в строку, только оно и останется "текстовым выражением", т.к. строки компилятор уже не обрабатывает.

Где то даже читал, что были попытки написать "несколько-проходный" компилятор, чтобы препроцессор+компилятор вызывались дважды для решения подобных проблем. Но поскольку это не было стандартизовано, то все так и осталось как есть...

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


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

16 минут назад, Baser сказал:

Где то даже читал, что были попытки написать "несколько-проходный" компилятор, чтобы препроцессор+компилятор вызывались дважды для решения подобных проблем. Но поскольку это не было стандартизовано, то все так и осталось как есть...

Спасибо, для меня это тоже опыт.

Собственно говоря, на нет и суда нет - немного пересмотрел процедуру обмена информацией о версии, дате и времени сборки проекта - получилось не так красиво, как изначально хотелось, но результат похожий.

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


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

On 4/17/2019 at 7:12 PM, Arlleex said:

Нет, так не работает.

#include  <stdio.h>

#define _BUILD_D ((unsigned int)((__DATE__[4] == ' ')?(__DATE__[5] - '0'):((__DATE__[4] - '0')*10 + (__DATE__[5] - '0'))))
#define BUILD_D _BUILD_D

int main(void)
{
    printf("%d\n", BUILD_D);
    
    return 0;
}

Только что специально проверил. Работает.

Печатает 5. Сегодня 5 июня.

Более того работает и без промежуточного дефайна.

 

#include  <stdio.h>
  
int main(void)
{
    const char buildString[] = "This build XXXX was compiled at " __DATE__ ", " __TIME__ ".";
            
    printf("%s\n", buildString);
    
    return 0;
}

или так: This build XXXX was compiled at Jun  5 2019, 14:46:24.

 

Перечитал весь топик сначала и понял что мой ответ не совсем в кассу.

Зато есть идея поменять локаль чтобы __DATA__ и __TIME__ сразу были в нужном формате.

ТС не пробовали так?

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


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

Короче говоря, инициализировать константу при помощи обращения по индексу к __DATE__ или __TIME__ в режиме Си не позволительно.

const int i = __DATE__[7];

avr-gcc-5.4.0 error: initializer element is not constant
Это канает только в С++ (((

Поэтому ИМХО выход один - спускать из makefile свои дефайны:

CFLAGS += -DBUILD_YEAR=$(shell date +"%Y")
CFLAGS += -DBUILD_MONTH=$(shell date +"%m")
CFLAGS += -DBUILD_DAY=$(shell date +"%d")
CFLAGS += -DBUILD_HOUR=$(shell date +"%H")
CFLAGS += -DBUILD_MIN=$(shell date +"%M")
CFLAGS += -DBUILD_SEC=$(shell date +"%S")

и юзать их как заблагорассудится

#define STR(S)  #S
#define XSTR(S) STR(S)


const char copyright[] = "(C) Ай да я "XSTR(BUILD_YEAR);
puts(copyright);

output: (C) Ай да я 2019

 

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


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

В gcc version 8.3.0 (Ubuntu 8.3.0-6ubuntu1) тоже работает.

А в этих компиляторах нет:

gcc version 5.4.0 (AVR-GCC)

gcc version 7.3.1 20180622 (release) [ARM/embedded-7-branch revision 261907] (15:7-2018-q2-6)

 

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


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

3 часа назад, demiurg_spb сказал:

Поэтому ИМХО выход один - спускать из makefile свои дефайны:


CFLAGS += -DBUILD_YEAR=$(shell date +"%Y")
CFLAGS += -DBUILD_MONTH=$(shell date +"%m")
CFLAGS += -DBUILD_DAY=$(shell date +"%d")
CFLAGS += -DBUILD_HOUR=$(shell date +"%H")
CFLAGS += -DBUILD_MIN=$(shell date +"%M")
CFLAGS += -DBUILD_SEC=$(shell date +"%S")

и юзать их как заблагорассудится

А случается ли у вас работа в полночь-заполночь?

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


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

On 6/26/2019 at 9:37 PM, Vladivolt said:

А случается ли у вас работа в полночь-заполночь?

Да не атомарно, но поправимо. Я это накидал для теста.

Траблы могут быть на границе каждой минуты...

	FULL_DT := $(shell date +"%Y %m %d %H %M %S")
	CFLAGS += -DBUILD_YEAR=$(shell echo $(FULL_DT) | cut -d' ' -f1)
	CFLAGS += -DBUILD_MONTH=$(shell echo $(FULL_DT) | cut -d' ' -f2)
	CFLAGS += -DBUILD_DAY=$(shell echo $(FULL_DT) | cut -d' ' -f3)
	CFLAGS += -DBUILD_HOUR=$(shell echo $(FULL_DT) | cut -d' ' -f4)
	CFLAGS += -DBUILD_MIN=$(shell echo $(FULL_DT) | cut -d' ' -f5)
	CFLAGS += -DBUILD_SEC=$(shell echo $(FULL_DT) | cut -d' ' -f6)

Вот так атомарно)

Надо бы тему переименовать в "Разбираемся с __DATE__ __TIME__"

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


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

И снова здравствуйте:wink:

Может подскажет кто, есть ли средство на этапе препроцессирования получить из числа A число B, которое является бит-реверсным значением этого A?

То есть, провернуть такую хитрость

#define REVERSE_BIT_8(A) (тут некоторая магия)

...

switch(p)
{
  case REVERSE_BIT_8(0x10): ... break; // реально подставится 0x08
  case REVERSE_BIT_8(0xAA): ... break; // реально подставится 0x55
}

или это невозможно?

 

Бывает, просто, что значение статически известно, но в потоке данных отреверсировано. Не хотелось бы переводить параметр в реверс-значение, тратя такты процессора, а, применив некий макрос, писать как удобно, при этом само значение будет реверсным для компилятора.

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


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

11 минут назад, Arlleex сказал:

Не хотелось бы переводить параметр в реверс-значение, тратя такты процессора, а, применив некий макрос, писать как удобно, при этом само значение будет реверсным для компилятора.

Одну команду пожалели?  :wink:

А каков весь диапазон возможных значений аргумента? Байт? Тогда можно тупо в лоб - через таблицу из 256 задефайненных констант преобразовать.  :wink:

Ну или написать макрос, переставляющий биты: M(x) ((x) << 7 & 128 | (x) << 6 & 64 | ...)

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


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

Приветствую!

Ручками ваяете  по подобию сего ужаса 

#define rev32bit(x) ( \
  (((x) & 0x00000001)<<31) | \
  (((x) & 0x00000002)<<29) | \
  ...
  (((x) & 0x00010000)>> 1) | \
  (((x) & 0x00020000)>> 3) | \
  ...                   
  (((x) & 0x80000000)>>31) )

Удачи! Rob.

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


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

52 минуты назад, jcxz сказал:

Одну команду пожалели?  :wink:

А каков весь диапазон возможных значений аргумента? Байт? Тогда можно тупо в лоб - через таблицу из 256 задефайненных констант преобразовать.

Ну или написать макрос, переставляющий биты.

Пожалел:biggrin: Да просто алгоритм постоянно долбит одно и то же действие, не хотелось его еще этим напрягать...

Короче, развернул это

u8 ReverseBitByte(u8 Data)
{
  Data = ((Data >> 4) & 0x0F) | ((Data << 4) & 0xF0);
  Data = ((Data >> 2) & 0x33) | ((Data << 2) & 0xCC);
  Data = ((Data >> 1) & 0x55) | ((Data << 1) & 0xAA);

  return Data;
}

в это (да простит меня тот, кто, возможно, однажды глянет мой .h-файл с навороченными макросами)

#define REV_8(x) (((((((((x) >> 4 & 0x0F) | ((x) << 4 & 0xF0)) >> 2) & 0x33) | (((((x) >> 4 & 0x0F) | ((x) << 4 & 0xF0)) << 2) & 0xCC)) >> 1) & 0x55) | ((((((((x) >> 4 & 0x0F) | ((x) << 4 & 0xF0)) >> 2) & 0x33) | (((((x) >> 4 & 0x0F) | ((x) << 4 & 0xF0)) << 2) & 0xCC)) << 1) & 0xAA))

 

45 минут назад, RobFPGA сказал:

Ручками ваяете  по подобию сего ужаса...

Спасибо, постараюсь оформить как-нибудь покрасивше и реализовать макросы для реверса тетрады, байта, полуслова, слова и двойного слова. Как показывает практика, это полезная штука:good2:

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


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

21 hours ago, Arlleex said:

в это (да простит меня тот, кто, возможно, однажды глянет мой .h-файл с навороченными макросами)

#define _f0(x)   (((x) & 0xF0) >> 4 | ((x) & 0x0F) << 4)
#define _cc(x)   (((x) & 0xCC) >> 2 | ((x) & 0x33) << 2)
#define _aa(x)   (((x) & 0xAA) >> 1 | ((x) & 0x55) << 1)

#define REV_BYTE(x) _aa(_cc(_f0(x)))

- так нагляднее будет)
 

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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