Вопросы по С/С++ (СИ)
- blackx
- Говорящий с текстолитом
- Сообщения: 1518
- Зарегистрирован: Пт дек 28, 2012 21:56:46
- Откуда: St. Petersburg
Re: Вопросы по С/С++ (СИ)
pokk, компилятор отделяет литералы от идентификаторов еще при проведении синтаксического анализа, используя правила их записи, которые исключают всякие неоднозначности. Все "слова" в программе разделяются на:
ключевые: unsigned char, int, extern;
литералы: "Hello", 0x10, 6, 14d, 5, 'C';
идентификаторы: nn, mas, LEN, _hello, a3243;
недопустимые последовательности: 43554acbde, 0myname, 0.555.3, "Hello;
Препроцессор действует точно также, как и компилятор. Сначала разбивает код макроса на синтаксическое дерево - определяет что где на основе заданных признаков (например, если первый символ - цифра или кавычки - значит однозначно не идентификатор), затем уже проводит его семантический анализ - проверяет "смысл" - находится ли идентификатор в списке аргументов макроса, например, или нет, в зависимости от этого заменяет его при обработке макросов или не заменяет. В случае с "nn" - такая запись сразу воспринимается как литерал, и препроцессор его конечно заменить не может.
ключевые: unsigned char, int, extern;
литералы: "Hello", 0x10, 6, 14d, 5, 'C';
идентификаторы: nn, mas, LEN, _hello, a3243;
недопустимые последовательности: 43554acbde, 0myname, 0.555.3, "Hello;
Препроцессор действует точно также, как и компилятор. Сначала разбивает код макроса на синтаксическое дерево - определяет что где на основе заданных признаков (например, если первый символ - цифра или кавычки - значит однозначно не идентификатор), затем уже проводит его семантический анализ - проверяет "смысл" - находится ли идентификатор в списке аргументов макроса, например, или нет, в зависимости от этого заменяет его при обработке макросов или не заменяет. В случае с "nn" - такая запись сразу воспринимается как литерал, и препроцессор его конечно заменить не может.
only pure true norwegian blackx 
- Реклама
Re: Вопросы по С/С++ (СИ)
Благодарю за помощь.
Kavka, Во втором примере как раз что надо было.
как я понял # подставляет " ".
blackx, Я очень часто встречал такую конструкцию
и меня всё интересовала для чего она нужна. Но всё таки руки так и не доходили по смотреть.
А тут по приведённой выше ссылки встретил такое
Как я понял из этого, эта конструкция нужна, для того что бы макросу можно было передать x == 0 но как она помогает так и не ясно.
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);Re: Вопросы по С/С++ (СИ)
Почему в макросах используют do while(0) можно прочитать например здесь.
Re: Вопросы по С/С++ (СИ)
доброго времени суток тут опять ковыряюсь с Си, много насмотрелся много начитался решил попрактиковаться и понял что ниче не понимаю)) к делу
в общем поставил задачу при нажатии кнопки выводить надпись на дисплей on off, с нуля естественно ничего написать не получиться взял код для дисплея проверил работает надписи выводит и код зажигания диода при нажатии кнопки в теории казалось что ничего сложного нет, как только принялся за дело то понял что и слова связать не могу. Прошу помощи! обьясните доходчиво как и что(на этих двух кусках кода) чувствую что осталось чуть чуть для того чтобы понять как это работает)
в общем поставил задачу при нажатии кнопки выводить надпись на дисплей 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: Вопросы по С/С++ (СИ)
а что вам тут непонятно то..?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: Вопросы по С/С++ (СИ)
начитаться я уже начитался, только вот пользоваться не умею/ не получается. мне кажется пару тройку примеров разобрать и пойдет потихоньку.
Вот например в данном примере мне непонятно как сделать чтобы ушла команда на дисплей что взято значение из порта D и после проинвертировано и отправлено в порт B
Вот например в данном примере мне непонятно как сделать чтобы ушла команда на дисплей что взято значение из порта D и после проинвертировано и отправлено в порт B
- unalex
- Мучитель микросхем
- Сообщения: 424
- Зарегистрирован: Сб авг 25, 2007 22:02:05
- Откуда: Германия, Viernheim
Re: Вопросы по С/С++ (СИ)
из второго листинга видно что дисплей подключен к порту D, а не к B, в этом и кроется проблема, меняйте его на B и дальше можно думать что посылать и какmastech писал(а):мне непонятно как сделать чтобы ушла команда на дисплей что взято значение из порта D и после проинвертировано и отправлено в порт B
Коктейль "Рекурсивный": 20% спирта, 30% воды, 50% коктейля "Рекурсивный"...
- Мikа
- Потрогал лапой паяльник
- Сообщения: 343
- Зарегистрирован: Пн апр 01, 2013 15:13:40
- Откуда: Москва
Re: Вопросы по С/С++ (СИ)
Парни, привет, такой ленивый и не умный вопрос от меня:
Если я заключу код типа
в функцию (чтобы удобнее было читать программу и она красивее(о, да, КРАСИВЕЕ!!!11), выглядела, я что-то потеряю в плане памяти и тактов исполнения? Хотя да, наверное, потеряю, это же обращение к функции, переход куда-то, лишний код и т.п... Но так, навскидку, что потеряется по битам\байтам памяти?
UPD: А я нашёл, как код свернуть в "+"
Так что вопрос отменяется 
Если я заключу код типа
Код: Выделить всё
if (cs != 6)
{
cs++;
}
else
{
cs=1;
}UPD: А я нашёл, как код свернуть в "+"
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Потому что хочу научиться.
Re: Вопросы по С/С++ (СИ)
Можно еще красивее сделать
Код: Выделить всё
if (++cs >= 6) cs=1;- Мikа
- Потрогал лапой паяльник
- Сообщения: 343
- Зарегистрирован: Пн апр 01, 2013 15:13:40
- Откуда: Москва
Re: Вопросы по С/С++ (СИ)
shads, я несколько раз перечитал, но не понимаю, как ваш код может быть равен тому, что я написал выше. Может дико туплю, но, правда, я его вижу так:
Если (cs, увеличенное на 1) больше\равно 6, тогда cs=1, иначе идём дальше.
Не помешал бы словарь сокращений
UPD: Парни, вот ещё чё. Если мне надо каждую секунду поднимать флаг А, то можно это делать в обработчике прерывания по таймеру. А можно не писать обработчик, а просто проверять, поднят ли флаг данного прерывания в соответствующем регистре? Ну и если поднят, делать то, что хочу и там же его программно сбрасывать. Это я про ATmega AVR.
Если (cs, увеличенное на 1) больше\равно 6, тогда cs=1, иначе идём дальше.
Не помешал бы словарь сокращений
UPD: Парни, вот ещё чё. Если мне надо каждую секунду поднимать флаг А, то можно это делать в обработчике прерывания по таймеру. А можно не писать обработчик, а просто проверять, поднят ли флаг данного прерывания в соответствующем регистре? Ну и если поднят, делать то, что хочу и там же его программно сбрасывать. Это я про ATmega AVR.
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Потому что хочу научиться.
Re: Вопросы по С/С++ (СИ)
Если ++ стоит впереди, то сначала будет инкремент потом сравнение.Мikа писал(а):shads, я несколько раз перечитал, но не понимаю, как ваш код может быть равен тому, что я написал выше.
Если расписать подробнее:
Код: Выделить всё
cs++;
if (cs >= 6) cs=1;Забабахайте в inline - размер малость возрастет, но скорость выше будет.Мikа писал(а):в функцию (чтобы удобнее было читать программу и она красивее(о, да, КРАСИВЕЕ!!!11),
Re: Вопросы по С/С++ (СИ)
В общем суть одна...Мikа писал(а):не понимаю, как ваш код может быть равен тому, что я написал выше.
Вот ваш вариант:
А вот мой вариант:
Re: Вопросы по С/С++ (СИ)
По моему опыту, AVR-GCC (20100110) иногда неадекватно реагирует на явно указанный inline. Но, однако, сам по себе часто инлайнит короткие функции сам, без подсказок.Забабахайте в inline - размер малость возрастет, но скорость выше будет.
Разница между теорией и практикой на практике гораздо больше, чем в теории.
- unalex
- Мучитель микросхем
- Сообщения: 424
- Зарегистрирован: Сб авг 25, 2007 22:02:05
- Откуда: Германия, Viernheim
Re: Вопросы по С/С++ (СИ)
а мне такая красота нравится
Код: Выделить всё
cs!=6 ? cs++ : cs=1;Коктейль "Рекурсивный": 20% спирта, 30% воды, 50% коктейля "Рекурсивный"...
- unalex
- Мучитель микросхем
- Сообщения: 424
- Зарегистрирован: Сб авг 25, 2007 22:02:05
- Откуда: Германия, Viernheim
Re: Вопросы по С/С++ (СИ)
так тоже прикольно
Код: Выделить всё
cs = (cs!=6 ? cs : 0) + 1;Коктейль "Рекурсивный": 20% спирта, 30% воды, 50% коктейля "Рекурсивный"...
Re: Вопросы по С/С++ (СИ)
Как в компиляторе IAR при компиляции разместить структуру по определённому адресу ?
делаю вот так вот
вроде всё нормально компилятор не ругается но и не размешает по заданному адресу возможно из за того что NetConf123 не где не используется.
Этой переменной хочу просто выделить область памяти в которой будут хранится настройки.
При старте программы я из этой области читаю настройки в переменную NetConf (которая находится в озу) и дальше работаю с ней. А в случае когда надо сохранить настройки пишу из NetConf в NetConf123.
А когда пытаюсь считать NetConf123 в главном цикле то выскакивает ошибка
Наверное можно как-то в файле линкера добавить секцию и тд.. но мне не сильно охота его изменять.
делаю вот так вот
Код: Выделить всё
#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;Этой переменной хочу просто выделить область памяти в которой будут хранится настройки.
При старте программы я из этой области читаю настройки в переменную NetConf (которая находится в озу) и дальше работаю с ней. А в случае когда надо сохранить настройки пишу из NetConf в NetConf123.
А когда пытаюсь считать NetConf123 в главном цикле то выскакивает ошибка
Код: Выделить всё
Error[Lp025]: absolute section .data (main.o #128) ([0x080e0000-0x080e004b]) overlaps with absolute section .data (main.o #117) ([0x080e0000-0x080e004b]) - Мikа
- Потрогал лапой паяльник
- Сообщения: 343
- Зарегистрирован: Пн апр 01, 2013 15:13:40
- Откуда: Москва
Re: Вопросы по С/С++ (СИ)
Парни, огромное спасибо, есть что записть в блокнотик
Моё непонимание крылось в том, что я считал, что в скобках условия if() действия происходят только для сравнения, а потом отменяются. То есть елси стоит, например c++ > 1, то после проверки с останется не увеличенным на 1 
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Потому что хочу научиться.
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Скажем так, этот код не равносилен тому что выше у автора вопроса. В исходном варианте если на вход придёт число, большее 6, оно будет инкрементироваться "до посинения" (в смысле, до переполнения, в зависимости от типа char/int/long...). И только после переполнения оно зациклится в диапазоне 1..6. Ваш вариант не имеет такого переполнения, так как проверяется не равенство, а условие больше/равно.shads писал(а):Можно еще красивее сделатьКод: Выделить всё
if (++cs >= 6) cs=1;
Хотя, скорее всего автор вопроса именно такого поведения и хотел (цикл в диапазоне 1..6), я не вижу, где вариант с переполнением в принципе может быть нужен.
P.S. Я бы вообще как-то так зациклил:
cs = (cs > 5) ? 1 : ++cs
- Мikа
- Потрогал лапой паяльник
- Сообщения: 343
- Зарегистрирован: Пн апр 01, 2013 15:13:40
- Откуда: Москва
Re: Вопросы по С/С++ (СИ)
WiseLord, да, вы правы, я искал зацикливания 1-6. А щас такой вот вопрос возник.
На словах: есть переменная а. Есть функция, с переменным значением С. Я хочу выполнить функцию, чтобы она посчиталась для а. Но не считается. Я что-то не так написал?
Код: Выделить всё
unsigned char a=1;
unsigned char b=0;
void func(unsigned char C)
{
b=c++;
}
func(a);Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Потому что хочу научиться.
- vitalik_1984
- Поставщик валерьянки для Кота
- Сообщения: 2482
- Зарегистрирован: Пт авг 27, 2010 05:57:06
- Откуда: Тюмень
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
А как должно работать?
Я бы предложил другой вариант:
Кстати ваша ошибка кроется возможно в постинкременте
Стоппп а ничего, что c и C это разные переменные?
Я бы предложил другой вариант:
Код: Выделить всё
unsigned char a=1;
unsigned char b=0;
void func(unsigned char c )
{
return ++c;
}
b=func(a); Стоппп а ничего, что c и C это разные переменные?


