Страница 173 из 386
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт дек 10, 2013 07:58:28
blackx
pokk, компилятор отделяет литералы от идентификаторов еще при проведении синтаксического анализа, используя правила их записи, которые исключают всякие неоднозначности. Все "слова" в программе разделяются на:
ключевые: unsigned char, int, extern;
литералы: "Hello", 0x10, 6, 14d, 5, 'C';
идентификаторы: nn, mas, LEN, _hello, a3243;
недопустимые последовательности: 43554acbde, 0myname, 0.555.3, "Hello;
Препроцессор действует точно также, как и компилятор. Сначала разбивает код макроса на синтаксическое дерево - определяет что где на основе заданных признаков (например, если первый символ - цифра или кавычки - значит однозначно не идентификатор), затем уже проводит его семантический анализ - проверяет "смысл" - находится ли идентификатор в списке аргументов макроса, например, или нет, в зависимости от этого заменяет его при обработке макросов или не заменяет. В случае с "nn" - такая запись сразу воспринимается как литерал, и препроцессор его конечно заменить не может.
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт дек 10, 2013 09:36:31
pokk
Благодарю за помощь.
Kavka, Во втором примере как раз что надо было.
Код: Выделить всё
#define TXT_RU(nn) LEN=UTF_8(#nn,mas);send(s,mas,LEN)
как я понял # подставляет " ".
blackx, Я очень часто встречал такую конструкцию
Код: Выделить всё
#define TXT_RU(nn) do { ....... } while (0);
и меня всё интересовала для чего она нужна. Но всё таки руки так и не доходили по смотреть.
А тут по приведённой выше ссылки встретил такое
The do and while (0) are a kludge to make it possible to write WARN_IF (arg);, which the resemblance of WARN_IF to a function would make C programmers want to do;
Код: Выделить всё
#define WARN_IF(EXP) \
do { if (EXP) \
fprintf (stderr, "Warning: " #EXP "\n"); } \
while (0)
WARN_IF (x == 0);
==> do { if (x == 0)
fprintf (stderr, "Warning: " "x == 0" "\n"); } while (0);
Как я понял из этого, эта конструкция нужна, для того что бы макросу можно было передать x == 0 но как она помогает так и не ясно.
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт дек 10, 2013 14:19:01
BorisSPB
Почему в макросах используют
do while(0) можно прочитать например
здесь.
Re: Вопросы по С/С++ (СИ)
Добавлено: Ср дек 18, 2013 12:39:31
mastech
доброго времени суток тут опять ковыряюсь с Си, много насмотрелся много начитался решил попрактиковаться и понял что ниче не понимаю)) к делу
в общем поставил задачу при нажатии кнопки выводить надпись на дисплей on off, с нуля естественно ничего написать не получиться взял код для дисплея проверил работает надписи выводит и код зажигания диода при нажатии кнопки в теории казалось что ничего сложного нет, как только принялся за дело то понял что и слова связать не могу. Прошу помощи! обьясните доходчиво как и что(на этих двух кусках кода) чувствую что осталось чуть чуть для того чтобы понять как это работает)
Спойлер
Код: Выделить всё
#include <avr/io.h>
int main (void)
{
DDRD = 0x00; //порт D - вход
PORTD = 0xFF; //подключаем нагрузочный резистор
DDRB = 0xFF; //порт B - выход
PORTB = 0x00; //устанавливаем 0 на выходе
while(1)
{
PORTB = ~PIND; //~ знак поразрядного инвертирования
}
}
Спойлер
Код: Выделить всё
#include <avr/io.h> //библиотека ввода/вывода
#include <util/delay.h>
#define RS 2 //RS=PD2 - сигнал управления ЖКИ
#define E 3 //E=PD3 - сигнал управления ЖКИ
//Программа передачи команд в ЖКИ
void lcd_com (unsigned char lcd)
{ unsigned char temp;
temp=(lcd&~(1<<RS))|(1<<E); //RS=0 – это команда
PORTD=temp; //Выводим на portD старшую тетраду команды, сигналы RS, E
PORTD=temp&~(1<<E); //Сигнал записи команды
temp=((lcd*16)&~(1<<RS))|(1<<E); //RS=0 – это команда
PORTD=temp; //Выводим на portD младшую тетраду команды, сигналы RS, E
PORTD=temp&~(1<<E); //Сигнал записи команды
_delay_us(111); //Пауза для выполнения команды
}
//Программа записи данных в ЖКИ
void lcd_dat (unsigned char lcd)
{ unsigned char temp;
temp=(lcd|(1<<RS))|(1<<E); //RS=1 – это данные
PORTD=temp; //Выводим на portD старшую тетраду данных, сигналы RS, E
PORTD=temp&~(1<<E); //Сигнал записи данных
temp=((lcd*16)|(1<<RS))|(1<<E); //RS=1 – это данные
PORTD=temp; //Выводим на portD младшую тетраду данных, сигналы RS, E
PORTD=temp&~(1<<E); //Сигнал записи данных
_delay_us(100); //Пауза для вывода данных
}
//Программа иниализации ЖКИ
void lcd_init (void)
{
lcd_com(0x2c); // шина 4 бит, LCD - 2 строки
_delay_us(100);
lcd_com(0x0c); // включение дисплея дисплея, мигающий курсор
_delay_us(100);
lcd_com(0x06); // очистка дисплея
_delay_us(100);
}
//Основная программа
int main()
{
DDRD=0xfc; //Инициализация portD
PORTD=0x00;
_delay_us(100); //Задержка, чтобы ЖКИ успел включиться
lcd_init(); //Инициализация ЖКИ
lcd_com(0x80); //курсор в начало первой строки
lcd_dat('H'); //Вывод "хд44780"
lcd_dat('D');
lcd_dat('4');
lcd_dat('4');
lcd_dat('7');
lcd_dat('8');
lcd_dat('0');
lcd_com(0xc0); //Ставим курсор на начало 2-й строки ЖКИ
lcd_dat('W'); //Записываем "винстар"
lcd_dat('I');
lcd_dat('N');
lcd_dat('S');
lcd_dat('T');
lcd_dat('A');
lcd_dat('R');
lcd_dat(' ');
lcd_dat('L');
lcd_dat('C');
lcd_dat('D');
lcd_dat(')');
lcd_dat(')');
lcd_dat(')');
while(1) //бесконечный цикл
return 1;
}
Re: Вопросы по С/С++ (СИ)
Добавлено: Ср дек 18, 2013 14:18:25
dzrkot
mastech писал(а):доброго времени суток тут опять ковыряюсь с Си, много насмотрелся много начитался решил попрактиковаться и понял что ниче не понимаю)) к делу
в общем поставил задачу при нажатии кнопки выводить надпись на дисплей on off, с нуля естественно ничего написать не получиться взял код для дисплея проверил работает надписи выводит и код зажигания диода при нажатии кнопки в теории казалось что ничего сложного нет, как только принялся за дело то понял что и слова связать не могу. Прошу помощи! обьясните доходчиво как и что(на этих двух кусках кода) чувствую что осталось чуть чуть для того чтобы понять как это работает)
Спойлер
Код: Выделить всё
#include <avr/io.h>
int main (void)
{
DDRD = 0x00; //порт D - вход
PORTD = 0xFF; //подключаем нагрузочный резистор
DDRB = 0xFF; //порт B - выход
PORTB = 0x00; //устанавливаем 0 на выходе
while(1)
{
PORTB = ~PIND; //~ знак поразрядного инвертирования
}
}
Спойлер
Код: Выделить всё
#include <avr/io.h> //библиотека ввода/вывода
#include <util/delay.h>
#define RS 2 //RS=PD2 - сигнал управления ЖКИ
#define E 3 //E=PD3 - сигнал управления ЖКИ
//Программа передачи команд в ЖКИ
void lcd_com (unsigned char lcd)
{ unsigned char temp;
temp=(lcd&~(1<<RS))|(1<<E); //RS=0 – это команда
PORTD=temp; //Выводим на portD старшую тетраду команды, сигналы RS, E
PORTD=temp&~(1<<E); //Сигнал записи команды
temp=((lcd*16)&~(1<<RS))|(1<<E); //RS=0 – это команда
PORTD=temp; //Выводим на portD младшую тетраду команды, сигналы RS, E
PORTD=temp&~(1<<E); //Сигнал записи команды
_delay_us(111); //Пауза для выполнения команды
}
//Программа записи данных в ЖКИ
void lcd_dat (unsigned char lcd)
{ unsigned char temp;
temp=(lcd|(1<<RS))|(1<<E); //RS=1 – это данные
PORTD=temp; //Выводим на portD старшую тетраду данных, сигналы RS, E
PORTD=temp&~(1<<E); //Сигнал записи данных
temp=((lcd*16)|(1<<RS))|(1<<E); //RS=1 – это данные
PORTD=temp; //Выводим на portD младшую тетраду данных, сигналы RS, E
PORTD=temp&~(1<<E); //Сигнал записи данных
_delay_us(100); //Пауза для вывода данных
}
//Программа иниализации ЖКИ
void lcd_init (void)
{
lcd_com(0x2c); // шина 4 бит, LCD - 2 строки
_delay_us(100);
lcd_com(0x0c); // включение дисплея дисплея, мигающий курсор
_delay_us(100);
lcd_com(0x06); // очистка дисплея
_delay_us(100);
}
//Основная программа
int main()
{
DDRD=0xfc; //Инициализация portD
PORTD=0x00;
_delay_us(100); //Задержка, чтобы ЖКИ успел включиться
lcd_init(); //Инициализация ЖКИ
lcd_com(0x80); //курсор в начало первой строки
lcd_dat('H'); //Вывод "хд44780"
lcd_dat('D');
lcd_dat('4');
lcd_dat('4');
lcd_dat('7');
lcd_dat('8');
lcd_dat('0');
lcd_com(0xc0); //Ставим курсор на начало 2-й строки ЖКИ
lcd_dat('W'); //Записываем "винстар"
lcd_dat('I');
lcd_dat('N');
lcd_dat('S');
lcd_dat('T');
lcd_dat('A');
lcd_dat('R');
lcd_dat(' ');
lcd_dat('L');
lcd_dat('C');
lcd_dat('D');
lcd_dat(')');
lcd_dat(')');
lcd_dat(')');
while(1) //бесконечный цикл
return 1;
}
а что вам тут непонятно то..?
Вообще если хотите понять принцип программирования на С/С++, то лучше возьмите какую-нибудь книгу и прочитайте ( могу посоветовать С.Прата Язык программирования С++, или Дейтл Как программироовать на С++) я именно с этих книг учился, поймёте основы С++, в Си практически всё тоже самое, у меня особо проблем не возникло потом с программирование под С. Лучше этому действительно уделить пару месяцев, и потом уже не задавать таких вопросов, иначе понимание врядли прийдёт к вам...Я на cyberforume начинал, сидел и решалзадачки для студентов +пример и задания из книг, начинал в июле этого года, сейчас уже проблем не испытываю с написанием под мк,вообще думаю взяться за winAPI или в направлении UNIX начинать копать.
Просто до этого я так же, как и вы, знал выборочно базу, читая её по разным сайтам, совет просто как человека, бывшего в вашей ситуации, почитайте норм книги, можно и не С++, а обычный С, но понимание будет и смогёте алгоритмы писать дляуправления теми или иными вещами....Вообщем как-то так...
Три раза просить, что бы Вы прочитали Правила форума, это уже перебор.
Нарушение Правил форума п. 2.7
aen
Re: Вопросы по С/С++ (СИ)
Добавлено: Ср дек 18, 2013 19:12:08
mastech
начитаться я уже начитался, только вот пользоваться не умею/ не получается. мне кажется пару тройку примеров разобрать и пойдет потихоньку.
Вот например в данном примере мне непонятно как сделать чтобы ушла команда на дисплей что взято значение из порта D и после проинвертировано и отправлено в порт B
Re: Вопросы по С/С++ (СИ)
Добавлено: Ср дек 18, 2013 19:40:08
unalex
mastech писал(а):мне непонятно как сделать чтобы ушла команда на дисплей что взято значение из порта D и после проинвертировано и отправлено в порт B
из второго листинга видно что дисплей подключен к порту D, а не к B, в этом и кроется проблема, меняйте его на B и дальше можно думать что посылать и как
Re: Вопросы по С/С++ (СИ)
Добавлено: Чт дек 19, 2013 17:00:44
Мikа
Парни, привет, такой ленивый и не умный вопрос от меня:
Если я заключу код типа
в функцию (чтобы удобнее было читать программу и она красивее(о, да, КРАСИВЕЕ!!!11), выглядела, я что-то потеряю в плане памяти и тактов исполнения? Хотя да, наверное, потеряю, это же обращение к функции, переход куда-то, лишний код и т.п... Но так, навскидку, что потеряется по битам\байтам памяти?
UPD: А я нашёл, как код свернуть в "+"

Так что вопрос отменяется

Re: Вопросы по С/С++ (СИ)
Добавлено: Чт дек 19, 2013 17:23:28
shads
Можно еще красивее сделать
Re: Вопросы по С/С++ (СИ)
Добавлено: Чт дек 19, 2013 17:32:59
Мikа
shads, я несколько раз перечитал, но не понимаю, как ваш код может быть равен тому, что я написал выше. Может дико туплю, но, правда, я его вижу так:
Если (cs, увеличенное на 1) больше\равно 6, тогда cs=1, иначе идём дальше.
Не помешал бы словарь сокращений
UPD: Парни, вот ещё чё. Если мне надо каждую секунду поднимать флаг А, то можно это делать в обработчике прерывания по таймеру. А можно не писать обработчик, а просто проверять, поднят ли флаг данного прерывания в соответствующем регистре? Ну и если поднят, делать то, что хочу и там же его программно сбрасывать. Это я про ATmega AVR.
Re: Вопросы по С/С++ (СИ)
Добавлено: Чт дек 19, 2013 20:32:15
Psych
Мikа писал(а):shads, я несколько раз перечитал, но не понимаю, как ваш код может быть равен тому, что я написал выше.
Если ++ стоит впереди, то сначала будет инкремент потом сравнение.
Если расписать подробнее:
Без разницы, скомпилится одинаково.
Мikа писал(а):в функцию (чтобы удобнее было читать программу и она красивее(о, да, КРАСИВЕЕ!!!11),
Забабахайте в inline - размер малость возрастет, но скорость выше будет.
Re: Вопросы по С/С++ (СИ)
Добавлено: Чт дек 19, 2013 20:45:54
shads
Мikа писал(а):не понимаю, как ваш код может быть равен тому, что я написал выше.
В общем суть одна...
Вот ваш вариант:
А вот мой вариант:

Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 01:12:23
YS
Забабахайте в inline - размер малость возрастет, но скорость выше будет.
По моему опыту, AVR-GCC (20100110) иногда неадекватно реагирует на явно указанный inline. Но, однако, сам по себе часто инлайнит короткие функции сам, без подсказок.
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 01:33:35
unalex
а мне такая красота нравится
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 01:46:53
unalex
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 09:26:31
pokk
Как в компиляторе IAR при компиляции разместить структуру по определённому адресу ?
делаю вот так вот
Код: Выделить всё
#pragma location=0x080E0000
NETCONF NetConf123={1,2,3,4};
Спойлер
Код: Выделить всё
typedef struct _NETCONF
{
unsigned char mac[6];
unsigned long int IP;
unsigned int port;
unsigned long int gateway;
unsigned long int Mask;
NET_SNMP SNMP;
unsigned char bord_status;
unsigned long int IP_list[4];
}NETCONF;
вроде всё нормально компилятор не ругается но и не размешает по заданному адресу возможно из за того что NetConf123 не где не используется.
Этой переменной хочу просто выделить область памяти в которой будут хранится настройки.
При старте программы я из этой области читаю настройки в переменную NetConf (которая находится в озу) и дальше работаю с ней. А в случае когда надо сохранить настройки пишу из NetConf в NetConf123.
А когда пытаюсь считать NetConf123 в главном цикле то выскакивает ошибка
Код: Выделить всё
Error[Lp025]: absolute section .data (main.o #128) ([0x080e0000-0x080e004b]) overlaps with absolute section .data (main.o #117) ([0x080e0000-0x080e004b])
Наверное можно как-то в файле линкера добавить секцию и тд.. но мне не сильно охота его изменять.
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 12:04:54
Мikа
Парни, огромное спасибо, есть что записть в блокнотик

Моё непонимание крылось в том, что я считал, что в скобках условия if() действия происходят только для сравнения, а потом отменяются. То есть елси стоит, например c++ > 1, то после проверки с останется не увеличенным на 1

Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 12:59:27
WiseLord
shads писал(а):Можно еще красивее сделать
Скажем так, этот код не равносилен тому что выше у автора вопроса. В исходном варианте если на вход придёт число, большее 6, оно будет инкрементироваться "до посинения" (в смысле, до переполнения, в зависимости от типа char/int/long...). И только после переполнения оно зациклится в диапазоне 1..6. Ваш вариант не имеет такого переполнения, так как проверяется не равенство, а условие больше/равно.
Хотя, скорее всего автор вопроса именно такого поведения и хотел (цикл в диапазоне 1..6), я не вижу, где вариант с переполнением в принципе может быть нужен.
P.S. Я бы вообще как-то так зациклил:
cs = (cs > 5) ? 1 : ++cs
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 15:39:17
Мikа
WiseLord, да, вы правы, я искал зацикливания 1-6. А щас такой вот вопрос возник.
Код: Выделить всё
unsigned char a=1;
unsigned char b=0;
void func(unsigned char C)
{
b=c++;
}
func(a);
На словах: есть переменная а. Есть функция, с переменным значением С. Я хочу выполнить функцию, чтобы она посчиталась для а. Но не считается. Я что-то не так написал?
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 15:52:52
vitalik_1984
А как должно работать?
Я бы предложил другой вариант:
Код: Выделить всё
unsigned char a=1;
unsigned char b=0;
void func(unsigned char c )
{
return ++c;
}
b=func(a);
Кстати ваша ошибка кроется возможно в постинкременте
Стоппп а ничего, что c и C это разные переменные?