IgnisFatuus
Постоялец
Offline
|
|
« : 20-07-2015 17:51 » |
|
Товарищи, подскажите пожалуйста где у меня косяк? Имеется 16 бит числа. Биты с 15 по 11 - это часы от 0 до 23, биты 10-5 это минуты, биты 4-0 это секунды. //Шаг первый - делаю некие действия, получаю число int time = 41805
//в битовом представлении это 1010 0011 0100 1101
//мне нужны биты 1010 0 ... //я делаю int hours = ((time & 0xF800 ) >> 11);
//результат 19... //но 10100 - это же 20!!!!
//Дубль 2 - делаю некие действия, получаю число int time = 42280
//в битовом представлении это 1010 0101 0010 1000
//мне нужны биты 1010 0 ... //я делаю
int hours = ((time & 0xF800 ) >> 11); //результат 20... //Как так???
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #1 : 20-07-2015 18:17 » |
|
#include <stdio.h>
int main() { //Шаг первый - делаю некие действия, получаю число int time = 41805;
//в битовом представлении это //1010 0011 0100 1101
//мне нужны биты 1010 0 ... //я делаю int hours = ((time & 0xF800 ) >> 11);
//результат 19... //но 10100 - это же 20!!!! printf("Result 1 = %d\n", hours);
//Дубль 2 - делаю некие действия, получаю число time = 42280;
//в битовом представлении это //1010 0101 0010 1000
//мне нужны биты 1010 0 ... //я делаю
hours = ((time & 0xF800 ) >> 11); //результат 20... //Как так??? printf("Result 2 = %d\n", hours); return 0; } $ g++ ignis.cpp -o ignis $ ./ignis Result 1 = 20 Result 2 = 20 $
Что я делаю не так?
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
IgnisFatuus
Постоялец
Offline
|
|
« Ответ #2 : 20-07-2015 20:02 » |
|
Хм... А сдвиг от платформы зависит? А то у меня это наблюдалось на Android, там ARM. Вы, как я понимаю, это проверяли под x86 ?
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #3 : 20-07-2015 20:08 » |
|
Можно сделать unsigned int time; Eсли тип int 16 разрядный. знаковый бит может вводить поправки. Хотя не думаю. Нужно читать доку по ARM как там реализованы сдвиги.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #4 : 21-07-2015 05:37 » |
|
Судя по полученному значению похоже, что это действительно возникает из-за использования int, вместо unsigned int. Кстати посмотрел стандарт - параграф 6.5.7 пункт 5: The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1/2(^E2). If E1 has a signed type and a negative value, the resulting value is implementation-defined.
|
|
« Последнее редактирование: 21-07-2015 06:17 от darkelf »
|
Записан
|
|
|
|
IgnisFatuus
Постоялец
Offline
|
|
« Ответ #5 : 21-07-2015 10:54 » |
|
Помогло, спасибо. Однако, видимо, я что - то еще упускаю.Дело в том, что я занимаюсь изучением библиотеки FatFS и там- то эта проблема и возникла - дата и время там хранятся в своем формате, есть double word переменная 16 бит даты и 16 бит со временем. bit31:25 Year origin from the 1980 (0..127) bit24:21 Month (1..12) bit20:16 Day of the month(1..31) bit15:11 Hour (0..23) bit10:5 Minute (0..59) bit4:0 Second / 2 (0..29) Накидал тут простенькую программку, чтобы глянуть - а правильно будет время обрабатываться потом - вот что получилось : #include <iostream> #include <string.h> typedef unsigned long DWORD; typedef unsigned short WORD; int main() { time_t t = time(NULL); struct tm tm_ = *localtime(&t); WORD date; WORD time; DWORD variable = ((DWORD)(tm_.tm_year - 80) << 25) | (((DWORD)tm_.tm_mon + 1) << 21) | ((DWORD)tm_.tm_mday << 16) | ((DWORD)tm_.tm_hour << 11) | ((DWORD)tm_.tm_min << 5) | ((DWORD)((tm_.tm_sec >> 1))); memcpy(&time, &variable, sizeof(time)); date = (variable>> 16); std::cout << "time = " << time << std::endl; std::cout << "date = " << date << std::endl; tm last_mod; last_mod.tm_year = (((date & 0xFE00) >> 9) + 80); last_mod.tm_mon = ((date & 0x1E0) >> 5); if(last_mod.tm_mon != 0) last_mod.tm_mon -=1; last_mod.tm_mday = ((date & 0x1F)); int result_s = (((int)time & (int)0xF800) >> 11); last_mod.tm_hour = (unsigned)result_s; last_mod.tm_min = ((time & 0x7E0) >> 5); last_mod.tm_sec = ((time & 0x1F)); std::cout << "create TS " << mktime(&tm_) << std::endl; std::cout << "restored TS " << mktime(&last_mod) << std::endl; return 0; } На x86 вывод - time = 27725 date = 18165 create TS 1437474866 restored TS 1437471253 хотя я проверил все цифры (дата и время, год, месяц) полностью совпадают..
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #6 : 21-07-2015 11:46 » |
|
Вы при обратном пересчёте забыли секунды умножить на 2. #include <time.h> #include <iostream> #include <string.h> typedef unsigned long DWORD; typedef unsigned short WORD; int main(void) { time_t t = time(NULL); struct tm tm_ = *gmtime(&t); WORD wdate; WORD wtime; DWORD variable = ((DWORD)(tm_.tm_year - 80) << 25) | ((DWORD)(tm_.tm_mon + 1) << 21) | ((DWORD)tm_.tm_mday << 16) | ((DWORD)tm_.tm_hour << 11) | ((DWORD)tm_.tm_min << 5) | ((DWORD)((tm_.tm_sec >> 1))); printf("variable = %u (%x)\n", variable, variable); wtime = (variable & 0xffff); wdate = (variable >> 16); printf("time = %u (%x)\n", wtime, wtime); printf("date = %u (%x)\n", wdate, wdate);
struct tm last_mod = { 0 }; last_mod.tm_year = (((wdate >> 9) & 0x7F) + 80); last_mod.tm_mon = (((wdate >> 5) & 0xF) - 1); last_mod.tm_mday = ((wdate & 0x1F)); last_mod.tm_hour = ((wtime >> 11) & 0x1F); last_mod.tm_min = ((wtime >> 5) & 0x3F); last_mod.tm_sec = ((wtime & 0x1F) << 1);
t = mktime(&tm_); printf("create TS %u (%x)\n", t, t); t = mktime(&last_mod); printf("create TS %u (%x)\n", t, t); return 0; }
|
|
« Последнее редактирование: 21-07-2015 11:50 от darkelf »
|
Записан
|
|
|
|
Dale
|
|
« Ответ #7 : 21-07-2015 11:47 » |
|
Пара вопросов по ходу:
1. Как у этой модели ARM обстоит дело с endianness? 2. Не проще ли вместо чехарды со сдвигами и масками использовать bit fields?
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
IgnisFatuus
Постоялец
Offline
|
|
« Ответ #8 : 21-07-2015 12:10 » |
|
Огромное спасибо, все раработало.
Стало быть надо было еще поменять очередность сдвига и наложения маски?
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #9 : 21-07-2015 12:22 » |
|
Наверное не надо, у меня просто такой стиль кода. Если Вы в своём варианте добавите умножение секунд на 2: - last_mod.tm_sec = ((time & 0x1F)); + last_mod.tm_sec = ((time & 0x1F) << 1); , то заработает и Ваш вариант.
|
|
|
Записан
|
|
|
|
IgnisFatuus
Постоялец
Offline
|
|
« Ответ #10 : 21-07-2015 12:31 » |
|
Проблема была еще и в "прогреве буфера" ... //у меня tm last_mod;
//у Вас... tm last_mod = {0}; Еще раз огромное спасибо!
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #11 : 21-07-2015 12:50 » |
|
ну, не совсем "прогрев" - на самом деле, там есть признак учёта летнего/зимнего времени tm_isdst , который, может "неожиданно" влиять на результат. Лучше инициализировать структуры заполняемые по-частям, что-бы потом не иметь непонятных эффектов.
Ну и ещё у меня там gmtime(), опять-же что-бы временная зона не влияла на результат.
|
|
« Последнее редактирование: 21-07-2015 12:52 от darkelf »
|
Записан
|
|
|
|
IgnisFatuus
Постоялец
Offline
|
|
« Ответ #12 : 21-07-2015 12:55 » |
|
Работает и с моим localtime(), только надо как раз прогреть и секунды умножить.
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #13 : 29-07-2015 21:32 » |
|
typedef unsigned long DWORD; typedef unsigned short WORD; Другой проц и все сломается. Есть такой stdint.h — не пробовал? int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t. И полезно включать больше варнингов при компиляции: смешанные знаково‑бесзнаковые операции могут быть источником неожиданных проблем.
|
|
« Последнее редактирование: 29-07-2015 21:34 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
|