Страница 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а
Парни, привет, такой ленивый и не умный вопрос от меня:
Если я заключу код типа

Код: Выделить всё

if (cs != 6)
			{
				cs++;
			} 
			else
			{
				cs=1;
			}
в функцию (чтобы удобнее было читать программу и она красивее(о, да, КРАСИВЕЕ!!!11), выглядела, я что-то потеряю в плане памяти и тактов исполнения? Хотя да, наверное, потеряю, это же обращение к функции, переход куда-то, лишний код и т.п... Но так, навскидку, что потеряется по битам\байтам памяти?

UPD: А я нашёл, как код свернуть в "+" :) Так что вопрос отменяется :)

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт дек 19, 2013 17:23:28
shads
Можно еще красивее сделать

Код: Выделить всё

if (++cs >= 6)	cs=1;

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт дек 19, 2013 17:32:59
Мikа
shads, я несколько раз перечитал, но не понимаю, как ваш код может быть равен тому, что я написал выше. Может дико туплю, но, правда, я его вижу так:

Если (cs, увеличенное на 1) больше\равно 6, тогда cs=1, иначе идём дальше.

Не помешал бы словарь сокращений :D

UPD: Парни, вот ещё чё. Если мне надо каждую секунду поднимать флаг А, то можно это делать в обработчике прерывания по таймеру. А можно не писать обработчик, а просто проверять, поднят ли флаг данного прерывания в соответствующем регистре? Ну и если поднят, делать то, что хочу и там же его программно сбрасывать. Это я про ATmega AVR.

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт дек 19, 2013 20:32:15
Psych
Мikа писал(а):shads, я несколько раз перечитал, но не понимаю, как ваш код может быть равен тому, что я написал выше.
Если ++ стоит впереди, то сначала будет инкремент потом сравнение.
Если расписать подробнее:

Код: Выделить всё

 cs++;
if (cs >= 6)   cs=1;
Без разницы, скомпилится одинаково.
М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
а мне такая красота нравится

Код: Выделить всё

cs!=6 ? cs++ : cs=1;

Re: Вопросы по С/С++ (СИ)

Добавлено: Пт дек 20, 2013 01:46:53
unalex
так тоже прикольно

Код: Выделить всё

cs = (cs!=6 ? cs : 0) + 1;

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 писал(а):Можно еще красивее сделать

Код: Выделить всё

if (++cs >= 6)	cs=1;
Скажем так, этот код не равносилен тому что выше у автора вопроса. В исходном варианте если на вход придёт число, большее 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 это разные переменные?