Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вопрос по си
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Страницы: 1, 2
Павел_Б
Здравствуйте.
Вопрос чисто по си.
Знаю что писалось уже тысячу раз, но отыскать так и не получилось sad.gif
есть некоторая переменная char temp
нужно условие что старшая тетрада (старшие четыре бита) например равнялись 2
тоесть что-то типа
Код
if (temp ?? 0x20) {}

как сделать?
Подскажите пожалуйста.
Что старшая тетрада равна 2
Спасибо!
Палыч
if ( (temp & 0xF0) == 0x20) {}
Hellper
(temp >> 4 ) == 2
Павел_Б
Спасибо большое!!! rolleyes.gif
zltigo
QUOTE (Павел_Б @ Jul 22 2011, 18:12) *
Вопрос чисто по си.

Для чисто по 'C' есть буквари и на крайний случай раздел программирования для начинающих.
777777
Цитата(Hellper @ Jul 22 2011, 20:19) *
(temp >> 4 ) == 2

А таким способом пользоваться не следует. Потому что если придется сравтивать не с 2, а например с 8, то результат будет неправвильным.
Genius1
Цитата(777777 @ Jul 26 2011, 19:01) *
А таким способом пользоваться не следует. Потому что если придется сравтивать не с 2, а например с 8, то результат будет неправвильным.

Из-за того, что тип char?
Палыч
Цитата(Genius1 @ Jul 26 2011, 21:09) *
Из-за того, что тип char?
Из-за того, что тип signed char (вспомните: что происходит со знаком при сдвиге вправо отрицательного числа).
Genius1
Цитата(Палыч @ Jul 26 2011, 22:20) *
Из-за того, что тип signed char (вспомните: что происходит со знаком при сдвиге вправо отрицательного числа).

Ну я это и имел ввиду. Убедиться решил, что правильно думаю sm.gif
zltigo
QUOTE (777777 @ Jul 26 2011, 18:01) *
А таким способом пользоваться не следует.

Совершено нормальный способ. Надо смотреть, что эффективнее ложится на систему команд и оптимизируется. Для, например, старших тетрад 32битников подобный вариант предпочтительней.
QUOTE
Потому что если придется сравтивать не с 2, а например с 8, то результат будет неправвильным.

Проблема ведь не в том, с чем сравнивать, а что сравнивать. Тут со знаком действительно проблема, но скорее всего, автору НУЖНО использовать вместо отданного на откуп компилятору типу char, unsigned тип. Кроме того, сейчас уже char по умолчанию обычно беззнаковый и компилятору можно указать использовать беззнаковый char. Ну или, если уж действительно вдруг нужна работа с signed char или с любым вариантом, то явные преобразования еще никто не отменял.
(temp >> 4 ) == (char)0xF0 >> 4;
будет работать всегда.



Павел_Б
Уважаемые форумчане, подскажите пожалуйста наиболее оптимальный вариант поиска последовательности нескольких байт.
То есть есть последовательность байт, например
......0x05 0x51 0x12 0x64 0xC0 0x66 0x41..................................................

И вот мне нужно найти начало последовательности 0x64 0xC0 0x66
Как это сделать? smile3046.gif
Спасибо за внимание.
Палыч
Цитата(Павел_Б @ Aug 6 2011, 21:57) *
И вот мне нужно найти начало последовательности 0x64 0xC0 0x66
Как это сделать?
Для такой короткой последовательности наиболее оптимально решение "в лоб":
1. Ищется значение 0x64
2 Проверяем, что следующий байт равен 0xC0, а за ним идёт 0x66. Если - нет, то на п.1

Павел_Б
Цитата(Палыч @ Aug 6 2011, 21:14) *
Для такой короткой последовательности наиболее оптимально решение "в лоб":
1. Ищется значение 0x64
2 Проверяем, что следующий байт равен 0xC0, а за ним идёт 0x66. Если - нет, то на п.1

На словах я это представляю...

Слава VMLAB-у, путём доООолгих ошибок и проб радилась такая весчь:

temp=0;
do {temp++;}
while ((byte[temp] != 0x64) | (byte[(temp+1)] != 0xC0) | (byte[(temp+2)] != 0x66));
Палыч
Цитата(Павел_Б @ Aug 6 2011, 22:19) *
Слава VMLAB-у, путём доООолгих ошибок и проб радилась такая весчь
Да, примерно - так. Осталось дополнить выходом из цикла при условии, что весь массив byte был просмотрен, но совпадений не обнаружено.
Павел_Б
Цитата(Палыч @ Aug 6 2011, 21:26) *
Да, примерно - так. Осталось дополнить выходом из цикла при условии, что весь массив byte был просмотрен, но совпадений не обнаружено.

Да, верно, это тоже нужно учесть!
Спасибо! sm.gif
zltigo
QUOTE (Павел_Б @ Aug 6 2011, 20:19) *
Слава VMLAB-у, путём доООолгих ошибок и проб радилась такая весчь:

А подумать головой совсем нельзя было?
QUOTE
temp=0;
do {temp++;}
while ((byte[temp] != 0x64) | (byte[(temp+1)] != 0xC0) | (byte[(temp+2)] != 0x66));

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



Павел_Б
Цитата(zltigo @ Aug 6 2011, 21:42) *
А подумать головой совсем нельзя было?

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

Благо что последовательность где-то находится через 7-мь и далее символов...
Голова на ночь совсем ни как smile3046.gif
Idle
CODE
$ cat el.c
#include <stdlib.h>
#include <string.h>
#include <assert.h>

static void *eqpos(const void *buf, size_t buflen, const void *s, size_t slen)
{
if (slen > buflen)
return NULL;
for (size_t i = 0; i <= (buflen - slen); i++) {
char *pos = (char *)buf + i;
if (memcmp(pos, s, slen) == 0)
return pos;
}
return NULL;
}

int main()
{
const char *buf = "deadbeefcafe";
size_t buflen = strlen(buf);
const char *s;

s = "d";
assert((buf + 0) == eqpos(buf, buflen, s, strlen(s)));

s = "dead";
assert((buf + 0) == eqpos(buf, buflen, s, strlen(s)));

s = "none";
assert(NULL == eqpos(buf, buflen, s, strlen(s)));

s = "tooooooooooolarge";
assert(NULL == eqpos(buf, buflen, s, strlen(s)));

s = "cafe";
assert((buf + sizeof("deadbeef") - 1) == eqpos(buf, buflen, s, strlen(s)));

assert(buf == eqpos(buf, buflen, buf, buflen));

exit(EXIT_SUCCESS);
}
$ gcc el.c -Wall -g -O0 -std=gnu99
$ ./a.out
$
Павел_Б
Цитата(Idle @ Aug 6 2011, 23:57) *
CODE
$ cat el.c
#include <stdlib.h>
#include <string.h>
#include <assert.h>

static void *eqpos(const void *buf, size_t buflen, const void *s, size_t slen)
{
if (slen > buflen)
return NULL;
for (size_t i = 0; i <= (buflen - slen); i++) {
char *pos = (char *)buf + i;
if (memcmp(pos, s, slen) == 0)
return pos;
}
return NULL;
}

int main()
{
const char *buf = "deadbeefcafe";
size_t buflen = strlen(buf);
const char *s;

s = "d";
assert((buf + 0) == eqpos(buf, buflen, s, strlen(s)));

s = "dead";
assert((buf + 0) == eqpos(buf, buflen, s, strlen(s)));

s = "none";
assert(NULL == eqpos(buf, buflen, s, strlen(s)));

s = "tooooooooooolarge";
assert(NULL == eqpos(buf, buflen, s, strlen(s)));

s = "cafe";
assert((buf + sizeof("deadbeef") - 1) == eqpos(buf, buflen, s, strlen(s)));

assert(buf == eqpos(buf, buflen, buf, buflen));

exit(EXIT_SUCCESS);
}
$ gcc el.c -Wall -g -O0 -std=gnu99
$ ./a.out
$

Спасибо sm.gif
ветерок
Код
   DDRD = ~(1 << 2);

А вот эта строчка что делает ?
Idle
выставляет в единицу все биты кроме бита 2, 11111011
zltigo
QUOTE (Idle @ Aug 6 2011, 22:57) *

Универсально, но в силу этого громоздко.
ветерок
Цитата(Idle @ Aug 7 2011, 10:58) *
выставляет в единицу все биты кроме бита 2, 11111011

А что делает символ: ~ ?
А строчку (1 << 2)
Я понимал как взять единицу записать в младший разряд и сдвинуть влево на два бита .
Как так получилось что записать во все биты 1 ?
или (1 << 2) означает записать во все биты 1 кроме второго бита ?
Genius1
Цитата(ветерок @ Aug 7 2011, 12:31) *
А что делает символ: ~ ?
А строчку (1 << 2)
Я понимал как взять единицу записать в младший разряд и сдвинуть влево на два бита .
Как так получилось что записать во все биты 1 ?
или (1 << 2) означает записать во все биты 1 кроме второго бита ?

~ - поразрядная инверсия.
так что ~(1<<2) - взять единицу, сдвинуть на 2 разряда влево и побитно проинвертировать результат
ar__systems
Цитата(Павел_Б @ Aug 6 2011, 13:57) *
Уважаемые форумчане, подскажите пожалуйста наиболее оптимальный вариант поиска последовательности нескольких байт.
То есть есть последовательность байт, например
......0x05 0x51 0x12 0x64 0xC0 0x66 0x41..................................................

И вот мне нужно найти начало последовательности 0x64 0xC0 0x66
Как это сделать? smile3046.gif
Спасибо за внимание.

Почему бы вам не почитать Кнута? Это все такие базовые вещи, что просто стыдно должно быть их спрашивать.

Цитата(777777 @ Jul 26 2011, 12:01) *
А таким способом пользоваться не следует. Потому что если придется сравтивать не с 2, а например с 8, то результат будет неправвильным.

Для арма такой способ эффективнее, т.к. в нем сдвиг в любой инструкции к аргументу бесплатно можно применять.
Павел_Б
Как правильно конвертировать шестнадцатиричное число в десятичное?
Другими словами.
Есть переменная int x
оно например имеет значение 1F
а мне нужно его преображзовать в 2 символа char (y,z). где x будет иметь значение 3, а z=1
то есть конвертировать hex в dec
Заранее спасибо всем откликнувшимся.
Палыч
Цитата(Павел_Б @ Aug 9 2011, 18:07) *
нужно его преображзовать в 2 символа char (y,z). где x будет иметь значение 3, а z=1
В Вашем трансляторе отсутствует функция sprintf? Правда, она очень прожорлива к ресурсам МК... Для Вашего случая и собственную функцию написать не сложно. Что-то типа такого:
Код
int x;
char s[2];
s[0]= x/10 + '0';
s[1]= x%10 + '0';
Здесь отсутствует проверка на знак числа х. Кроме того, не подавляется первый ноль, в случае если число х<10, и выдаст неверный результат, если x>99... Доработайте сами под Ваши нужды.
Павел_Б
Цитата(Палыч @ Aug 9 2011, 18:51) *
В Вашем трансляторе отсутствует функция sprintf? Правда, она очень прожорлива к ресурсам МК... Для Вашего случая и собственную функцию написать не сложно. Что-то типа такого:
Код
int x;
char s[2];
s[0]= x/10 + '0';
s[1]= x%10 + '0';
Здесь отсутствует проверка на знак числа х. Кроме того, не подавляется первый ноль, в случае если число х<10, и выдаст неверный результат, если x>99... Доработайте сами под Ваши нужды.

Да, спасибо огромное.
Тут ещё вопрос назрел.
Как мне явно указать ячейку памяти в eeprom?
Тоесть в программе будет меняться значение переменной в eeprom. После включения мк должен считать значение из этой ячейки. В связи с чем вопрос.
Если я просто укажу ячейку как
eeprom char j;
И в программе она сменит значение. После нового включения я считаю значение переменной j из eeprom - она возъмёт из той же ячейки?

И правильно ли будет такой алгоритм. Есть таже переменная в памяти eeprom. В обработчике прерываний таймера который работает на высокой скорости я пишу, например:
if (j==0) {zz = 0;}
else {zz = 1;}
Просто насколько мне известно запись в eeprom занимает более 100 циклов тактового генератора. А вот чтение насколько быстро будет выполняться не знаю sad.gif
Спасибо.
MrYuran
Цитата(ветерок @ Aug 7 2011, 09:28) *
А вот эта строчка что делает ?

Скорее всего, имелось в виду DDRD &= ~(1 << 2);
Такая строчка сбрасывает нужный бит.
ветерок
Genius1 спасибо
MrYuran ,да точно там такая строка

(1 << 2)
то есть такой сдвиг двигает единичку а после себя ноль оставляет ?
Палыч
Цитата(ветерок @ Aug 10 2011, 15:14) *
(1 << 2)
то есть такой сдвиг двигает единичку а после себя ноль оставляет ?
Да, загляните уж в какой нибудь учебник по языку С!

DDRD &= ~(1 << 2);
1. Десятичная константа 1. Двоичное представление 00000001
2. (1<<2) Сдвиг константы влево на 2. Получаем 00000100
3. ~(1<<2) Побитовая инверсия = 11111011
4. DDRD &= ~(1 << 2) Это эквивалентно такой записи DDRD = DDRD & ( ~(1 << 2)). Если значение битов DDRD равно
(х7)(х6)(х5)(х4)(х3)(х2)(х1)(х0), то после побитового логического умножения на 11111011 получаем результат
(х7)(х6)(х5)(х4)(х3)(0)(х1)(х0), который и заносится в DDRD.

Т.е. фактически - сбрасывается в ноль второй бит регистра DDRD.
toweroff
bb-offtopic.gif
а как в С сделать именно "roll" битов?
при операциях << и >> дополняются нулями, а roll ? roll с флагом? Или, в очередной раз, отдаем на откуп оптимизатору?
операнд, разумеется, имеет разрядность МК
MrYuran
Цитата(toweroff @ Aug 10 2011, 20:22) *
bb-offtopic.gif
а как в С сделать именно "roll" битов?
при операциях << и >> дополняются нулями, а roll ? roll с флагом? Или, в очередной раз, отдаем на откуп оптимизатору?
операнд, разумеется, имеет разрядность МК

А никак. Инлайнить асм только. И это в принципе правильно. Слишком уж аппаратнозависимо.
toweroff
Цитата(MrYuran @ Aug 10 2011, 20:57) *
А никак. Инлайнить асм только. И это в принципе правильно. Слишком уж аппаратнозависимо.

ну и посему оффтопику офф sm.gif
sergeeff
Цитата(MrYuran @ Aug 10 2011, 20:57) *
А никак. Инлайнить асм только. И это в принципе правильно. Слишком уж аппаратнозависимо.


Да бросьте вы только про asm inline. Для примера:

Код
__inline BYTE RotateByteLeft(BYTE n, unsigned long i)
{
  return (n << i) | (n >> (8 - i));
}

__inline BYTE RotateByteRight(BYTE n, unsigned long i)
{
  return (n >> i) | (n << (8 - i));
}

toweroff
Цитата(sergeeff @ Aug 10 2011, 21:39) *
Для примера:


во-во, я про эти конструкции и говорил. То есть, все нормально ляжет в асм?
но проверить надо )

кстати, а как оно там с флагом?
ARV
Цитата(sergeeff @ Aug 10 2011, 20:39) *
Для примера:

Код
__inline BYTE RotateByteLeft(BYTE n, unsigned long i)
{
  return (n << i) | (n >> (8 - i));
}

__inline BYTE RotateByteRight(BYTE n, unsigned long i)
{
  return (n >> i) | (n << (8 - i));
}
или так:
Код
#define ROR(x,y) (((x) >> (y)) | ((x) << ((sizeof(x)*8 - (y)))
Smoky
Уважаемые коллеги, возможно ли использование указателей на битовые переменные?
zltigo
Для начала задумайтесь над тем, что Вы называете "битовой переменной". В зависимости от этого Вы сами сможете ответить на свой вопрос отрицательно, или положительно.
Flexz
Возможно, если архитектура поддерживает bit-banding.
Smoky
Цитата(zltigo @ Aug 11 2011, 23:33) *
Для начала задумайтесь над тем, что Вы называете "битовой переменной". В зависимости от этого Вы сами сможете ответить на свой вопрос отрицательно, или положительно.


Забыл сказать что я использую WinAVR. Жаль что Вы уклонились от ответа, в принципе я пробовал, не получилось. Потому мой ответ на мой вопрос отрицательный.

void detect_akk(byte *flag_prm,byte *indakk_prm,word *cloc_prm);

1064: case 1: detect_akk(&akk1.ucon,&akk1.index,&akk1.cloc1);break;

../Mcuzuaa.c:1064: warning: passing argument 1 of 'detect_akk' discards qualifiers from pointer target type
../Mcuzuaa.c:1064: warning: passing argument 2 of 'detect_akk' discards qualifiers from pointer target type
../Mcuzuaa.c:1064: warning: passing argument 3 of 'detect_akk' discards qualifiers from pointer target type

Уважаемые коллеги, если можно скажите в чём суть этих предупреждений, не могу понять. Хотя компиляция прошла успешно, всё же лучьше чтобы их небыло. Верхня строка прототип функции, следующая её вызов.
_Pasha
Цитата(дымок @ Aug 13 2011, 18:31) *
Уважаемые коллеги, если можно скажите в чём суть этих предупреждений, не могу понять. Хотя компиляция прошла успешно, всё же лучьше чтобы их небыло. Верхня строка прототип функции, следующая её вызов.

&akk1.ucon имеет тип void *
Параметры же другого типа.
Если указать в параметрах вызова функции (byte *)&akk1.ucon, матюк касательно первого параметра исчезнет, итд
Это, межпрочим, не пустые вопли, они влияют на оптимизацию и на обращения к volatile переменным, если таковые в списке параметров.
Smoky
Цитата(_Pasha @ Aug 13 2011, 21:38) *
&akk1.ucon имеет тип void *
Параметры же другого типа.
Если указать в параметрах вызова функции (byte *)&akk1.ucon, матюк касательно первого параметра исчезнет, итд
Это, межпрочим, не пустые вопли, они влияют на оптимизацию и на обращения к volatile переменным, если таковые в списке параметров.


Большое Вам спасибо, исправил и все предупреждения исчезли, а их было аж 42.
aaarrr
Цитата(дымок @ Aug 13 2011, 20:56) *
их было аж 42.

Кабы их было 1-2 осознанно внесенных, тогда можно было бы сказать, что исправили. А так - просто вбили костыль sad.gif
Smoky
Цитата(aaarrr @ Aug 14 2011, 02:11) *
Кабы их было 1-2 осознанно внесенных, тогда можно было бы сказать, что исправили. А так - просто вбили костыль sad.gif


Спасибо Вам за профессиональный "костыль". Просто у меня в программе около около десятка таких функций с подобными аргументами, потому и столько предупреждений.
aaarrr
Цитата(дымок @ Aug 14 2011, 14:18) *
Спасибо Вам за профессиональный "костыль". Просто у меня в программе около около десятка таких функций с подобными аргументами, потому и столько предупреждений.

Не должны потери квалификаторов измеряться десятками - скорее всего, это означает, что применены они не по делу.
Smoky
Цитата(aaarrr @ Aug 14 2011, 18:25) *
Не должны потери квалификаторов измеряться десятками - скорее всего, это означает, что применены они не по делу.


Я электронщик, программированием был вынужден заняться ибо без микроконтроллеров никуда. Отношу себя к начинающим, С изучал по учебному пособию Бредли Л.Джонса и Питера Эйткена. О передаче в функции адресов переменных в качестве аргументов описано весьма кратко. Если можно, укажите где можно почитать об этом более подробно. Спасибо.
aaarrr
Цитата(_Pasha @ Aug 13 2011, 19:38) *
&akk1.ucon имеет тип void *

Откуда вдруг void *?

Цитата(дымок @ Aug 14 2011, 17:50) *
О передаче в функции адресов переменных в качестве аргументов описано весьма кратко. Если можно, укажите где можно почитать об этом более подробно.

Увы, учебную литературу не подскажу - как-то так получилось, что ничего, кроме стандарта и справочников, по "C" не читал sad.gif

Расскажите, как в программе объявлен akk1, и почему он объявлен именно так.
Smoky
Цитата(aaarrr @ Aug 14 2011, 20:19) *
Расскажите, как в программе объявлен akk1, и почему он объявлен именно так.


Переменная akk1 объявлена глобально как структура, почему именно так? Скорее всего исходя из предыдущего опыта:

volatile struct
{
byte index;
byte numprg;
byte capind;
byte ucon;
byte hitmpr;
byte error;
byte outzrz;
word maxvlt;
word captr;
word cloc1;
word cloc2;
word tmpair;
dword sumcap;
}akk1;
aaarrr
А volatile действительно нужен? (Сам факт использования объекта в прерывании не является безусловным к тому показанием.)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.