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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

Видимо имелось ввиду условие не выполняется.
А работает то, как раз, правильно.Потому что это условие никогда не выполнится.

Ps. Лютик, Не нужно было добавлять от себя (()==1)макрос работает в том виде, как я привел.
В поисках истины человек развивается.
Контактная информация:
Реклама
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

vitalik_1984, я прекрасно понял, что имел ввиду Лютик, просто хотелось бы, что бы в следующий раз человек правильно задавал вопросы и пытался немного подумать головой.
Написать строку, сидеть и удивляться, что она не работает, не подумав - "а почему она не работает и почему вообще должна работать ?" - глупо. Достаточно просто разобрать её на части и немного пошевелить серым веществом (не в обиду) :)
По этому я и задал встречный вопрос - "почему она должна работать ?". Подобные вопросы должны были у Лютик'а сами образовываться в голове.
Это равносильно тому, что я напишу кучу разных символов в строке, буду сидеть и удивляться почему она не работает и ругать матом компилятор. :)
Контактная информация:
Реклама
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

Это распространенная ошибка - путать число "1" и булевое значение true.
while((PIND & (1<<6))==1);
while((PIND & (1<<6))== true);
совсем разные условия.
В общем, true - это значение, противоположное false, которое, в свою очередь, всегда равно 0.
Т.е true - это любое число, отличное от 0.
Если в первом случае PIND & (1<<6) будет составлять 0х40 , оно никак не будет равно 1, но будет удовлетворять второму условию выражения (это число, отличное от 0)
Далее, выражения
while((PIND & (1<<6))== true);
while((PIND & (1<<6)));
абсолютно идентичны.
Только недавно об этом писал... http://radiokot.ru/forum/viewtopic.php? ... 8#p1380428
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону

Сообщение Goldsmith »

urry писал(а):Это распространенная ошибка - путать число "1" и булевое значение true.
while((PIND & (1<<6))==1);
while((PIND & (1<<6))== true);
совсем разные условия.
Эта "ошибка" закреплена стандартами. Например, стандарт C99 (ISO/IEC 9899:1999 (E)):

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

7.16 Boolean type and values <stdbool.h>
...
3 The remaining three macros are suitable for use in #if preprocessing directives. They are
    true
which expands to the integer constant 1,
    false
which expands to the integer constant 0
Текст <stdbool.h> из GCC подтверждает:

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

...
#ifndef __cplusplus

#define bool	_Bool
#define true	1
#define false	0
...
В программе на C, которая включает стандартный заголовок <stdbool.h>, выражения

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

while((PIND & (1<<6))==1);
и

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

while((PIND & (1<<6))== true);
тождественны в силу приведенных макроопределений (и тем самым одинаково неправильны по сути). В C++ аналогично, только заголовок не понадобится, поскольку логический тип уже встроен в язык.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

while((PIND & (1<<6))==1);
и
Код:
while((PIND & (1<<6))== true);
тождественны в силу приведенных макроопределений (и тем самым одинаково неправильны по сути
-------------------------------------
Неправильны по сути из-за того, что выражение while((PIND & (1<<6)) будет исполняться при любых ненулевых значениях результата.
Попытка сравнить результат с "1" ни к чему хорошему не приведет.
В предыдущем посте я писал, что я переопределил true
#define true !false
После этого while((PIND & (1<<6))== true); будет выполняться правильно.
Насколько я отступаю от стандарта в этом случае - пока катастроф не видел.
Контактная информация:
Реклама
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

Из самого определения which expands to the integer constant 1 следует, что единицу мы получим в случае обратного преобразования, т.е. из bool в int например.
А в условиях идёт только проверка на 0, как уже расписал urry
Реклама
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

urry писал(а):Это распространенная ошибка - путать число "1" и булевое значение true.
while((PIND & (1<<6))==1);
while((PIND & (1<<6))== true);
совсем разные условия.
Совсем одинаковые в своей неправильности, как уже сказал Goldsmith
urry писал(а):В общем, true - это значение, противоположное false, которое, в свою очередь, всегда равно 0.
Т.е true - это любое число, отличное от 0.
Это когда мы от int преобразовываем к bool. Или когда проверяем в if / ?: / while / for
А когда от bool преобразовіваем к int, то получаем из true 1-ку.
В указанных условиях (PIND & (1<<6))==XXX мы сравниваем два целых числа (это С а не Паскаль!).
Одно получаем оператором побитового маскирования, приводящим по стандарту свои аргументы к int и возвращающим int (и только потом в процессе оптимизации это может сократиться к байтам или вообще к проверке бита порта одной командой).
Другое -- преобразованием XXX к int. При преобразовании 0 к логическому значению оператором логического отрицания ! получаем значение "истинно", которое потом при преобразовании к int для сравнивания превращается в 1. Собственно, оно еще раньше превращается в 1 для сокращения пути.
urry писал(а):Далее, выражения
while((PIND & (1<<6))== true);
while((PIND & (1<<6)));
абсолютно идентичны.
«Скажите мне, в каком компиляторе, чтобы я никогда им не пользовался»™
Идентичны, что неудивительно, следующие выражения:

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

    while(   (PIND & (1<<6))          ) ; // всё, что не 0 -- уже хорошо.
    while( !!(PIND & (1<<6)) == true  ) ; // всё, что при отрицании даёт 0 (false) и при последующем отрицании совпадает с true
    while(   (PIND & (1<<6)) != false ) ; // всё, что не совпадает с false
И они все (завёрнутые в функцию void foo() { то_выражение } ) дают одинаковый код в avr-gcc

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

foo:
.L1:
        sbic 48-32,6
        rjmp .L1
        ret
А вот

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

    while(   (PIND & (1<<6)) == 1     ) ; // всё, что совпадает 1.
    while(   (PIND & (1<<6)) == true  ) ; // всё, что совпадает с true, выраженном как целое число, т.е. всё, что равно 1.
от всех трёх выше отличаются и дают вполне ожидаемое

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

foo1:
        in r24,48-32
        ret
Именно поэтому писать в С if ( expression == true ) или совершенно бессмысленно (когда само expression даёт логическое значение, например, expression это (A == B) ), или ошибка, как в примерх выше. Если уж писать «булевские» значения, то if (expression != false), иногда такое встречал в чужом коде, но в чём кайф -- не понимаю.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону

Сообщение Goldsmith »

avreal писал(а):«Скажите мне, в каком компиляторе, чтобы я никогда им не пользовался»™
avreal, это просто наваждение какое-то! Уже не в первой теме так: только выдастся минутка написать ответ, захожу - а Вы уже все сказали, причем именно теми же словами, что и я собирался. Мистика :)

Началось в эпической теме про счетчики, переодетые сдвиговыми регистрами, и с тех пор который раз уже...
avreal писал(а):Если уж писать «булевские» значения, то if (expression != false), иногда такое встречал в чужом коде, но в чём кайф -- не понимаю.
Я видел вариант круче:

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

if (b.ToString().Length == 4) ...
, где b, разумеется, булевская переменная. Само собой, код родом из одной знойной страны, где программистов больше, чем населения.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

И началась битва титанов.... :))) Ploop,avreal
, urry,Goldsmith.
avreal писал(а):Именно поэтому писать в С if ( expression == true ) или совершенно бессмысленно (когда само expression даёт логическое значение, например, expression это (A == B) ), или ошибка, как в примерх выше. Если уж писать «булевские» значения, то if (expression != false), иногда такое встречал в чужом коде, но в чём кайф -- не понимаю.
Полностью согласен.Лучше уж пользоваться стандартным понятным макросом, доступно для чтения и не вызывает ошибок.
И к тому же оптимизатор компилятора уже привык к таким "изворотам речи", позволяя обойтись лишь одной командой,если проверяется только один бит порта.
Goldsmith писал(а):Я видел вариант круче:
Код:
if (b.ToString().Length == 4) ...
это типа если длина == 4, то считать что это TRUE? Бред какой то. :facepalm:
В поисках истины человек развивается.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону

Сообщение Goldsmith »

vitalik_1984 писал(а):И началась битва титанов.... :))) Ploop,avreal
, urry,Goldsmith.
Для битвы титанов предмет жидковат. Первый класс, вторая четверть. "Мама мыла раму"...
vitalik_1984 писал(а):это типа если длина == 4, то считать что это TRUE? Бред какой то. :facepalm:
Да, такой вот индийский креативчег.

Переменная b - булевского типа (фрагмент взят из программы на C#, там есть полноценный булевский тип, в отличие от неуклюжей имитации на C). Метод b.ToString() возвращает ее строковое представление ("true" либо "false"). Наконец, свойство b.ToString().Length возвращает длину этой строки (4 или 5 соответственно). Вся конструкция в целом эквивалентна банальному if (b) ...

Конструкция смешная и нелепая, но зато работает правильно (в отличие от тех, что обсуждались в упомянутой "битве"), и потому просочилась в релиз.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Контактная информация:
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1335
Зарегистрирован: Ср июн 09, 2010 16:44:54
Откуда: Пермь

Сообщение RomanT »

Помогиге начинающему самоучке ...

http://youtu.be/uTIopmsFF9U
Спойлер

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

void MP3_Test(char *test)
{
unsigned long i;
unsigned long roma;
roma=1;
 while(1)
 {

// char mp3_filename[14] = "sound.mp3";   // MP3 file name
 char mp3_filename[3][14] ={ "sound1.mp3","sound2.mp3","sound3.mp3"};

  // Reset error flag
  *test = 0;

  TFT_16bit_Write_Text("2. SD vigu", 30, 100);
  if (Mmc_Fat_Init() == 0) {
    if (Mmc_Fat_Assign(&mp3_filename[roma], 0) ) {
      TFT_16bit_Write_Text("3. fail est", 30, 120);
      Mmc_Fat_Reset(&file_size);          // Call Reset before file reading,
                                          //   procedure returns size of the file

      TFT_16bit_Write_Text("4. vosproizvodim:", 30, 140);
      TFT_16bit_Write_Text(&mp3_filename[roma], 150, 140);

      // send file blocks to MP3 SDI
      while (file_size > BUFFER_SIZE)
      {
        for (i=0; i<BUFFER_SIZE; i++)
        {
          Mmc_Fat_Read(mp3_buffer + i);
        }
        for (i=0; i<BUFFER_SIZE/BYTES_2_WRITE; i++) {
          MP3_SDI_Write_32(mp3_buffer + i*BYTES_2_WRITE);
        }

        file_size -= BUFFER_SIZE;
     }

      // send the rest of the file to MP3 SDI
      for (i=0; i<file_size; i++)
      {
        Mmc_Fat_Read(mp3_buffer + i);
      }

      for (i=0; i<file_size; i++)
      {
        MP3_SDI_Write(mp3_buffer[i]);
      }

      TFT_16bit_Write_Text(&mp3_filename[roma], 30, 160);
    }
    else {

      TFT_16bit_Write_Text("3. File not assigned", 30, 180);
      *test = 2;
    }
  }
  else {
    TFT_16bit_Write_Text("3. MMC FAT not initialized", 30, 200);
   *test = 2;
  }
 roma++;
 if (roma>3) { roma=1; }
 }
}
Хочу достигнуть, чтоб переменная mp3_filename принимала значения "sound1.mp3", "sound2.mp3", "sound3.mp3",
последовательно с каждым проходом в цикле ...
В данном случаи сразу принимает 2-е значение "sound2.mp3"
и в цикле идут поочереди 2 - 3 - 2 - 3 и т.д. (не когда не принимает значения "sound1.mp3" )

-----------------------

Мудно, проблема решилась изменением начального значения roma=0;
где оно увеличивается ? roma++ в конце цикла-же ...
Контактная информация:
Говорящий с текстолитом
Сообщения: 1658
Зарегистрирован: Вс дек 11, 2011 05:25:04
Откуда: Киев, Украина

Сообщение Tolmi »

Первый класс, вторая четверть. "Мама мыла раму"...
Индексы массивов в C начинаются с нуля...
In theory, theory and practice are the same. In practice, they're not.
Контактная информация:
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1335
Зарегистрирован: Ср июн 09, 2010 16:44:54
Откуда: Пермь

Сообщение RomanT »

Ну уж извините ... первый раз сел за Си ...
В школе только изучал Basic на 8-ми битных ямахах, потом собирал РК-86, Орион 128, синклеры ...
в совершенстве им (MS QBasic) овладел только после армии (1992-1994) ...

----------------------------

Ещё вопрос, как в char переменной написать несколько пробелов ?
Контактная информация:
Говорящий с текстолитом
Сообщения: 1658
Зарегистрирован: Вс дек 11, 2011 05:25:04
Откуда: Киев, Украина

Сообщение Tolmi »

RomanT писал(а):Ну уж извините ... первый раз сел за Си ...
Ну, кроме бэйсика я уж и не припомню языков, в которых индексы массива по умолчанию не начинались с нуля. В МС бэйсике, кстати, для этого тоже рукоятка для управления есть.
Ещё вопрос, как в char переменной написать несколько пробелов ?
Никак, по определению тип char - это один символ. Хотите много - используйте массивы.
Или указатели на строки. Впрочем, человеку в первый раз севшему за С, про указатели лучше пока забыть.
In theory, theory and practice are the same. In practice, they're not.
Контактная информация:
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1335
Зарегистрирован: Ср июн 09, 2010 16:44:54
Откуда: Пермь

Сообщение RomanT »

Вышел из ситуации перезаливкой экрана дисплея, в текущем цикле ...
Спойлер

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

  TFT_16bit_Fill_Screen(CL_WHITE_16bit);
  TFT_16bit_Set_Pen(CL_Black_16bit, 1);
  TFT_16bit_Line(20, 220, 300, 220);
  TFT_16bit_LIne(20,  46, 300,  46);
  TFT_16bit_Set_Font(&HandelGothic_BT21x22_Regular, CL_RED_16bit, FO_HORIZONTAL_16bit);
  TFT_16bit_Write_Text("POMA", 75, 14);
  TFT_16bit_Set_Font(&Verdana12x13_Regular, CL_BLACK_16bit, FO_HORIZONTAL_16bit);
  TFT_16bit_Write_Text("MP3 Player for ATmega", 19, 223);
  TFT_16bit_Set_Font(&Verdana12x13_Regular, CL_RED_16bit, FO_HORIZONTAL_16bit);
  TFT_16bit_Write_Text("www.ingineer.ru", 200, 223);
  TFT_16bit_Set_Font(&TFT_16bit_defaultFont, CL_BLACK_16bit, FO_HORIZONTAL_16bit);
Просто при смене надписи, следующая замазывала предидущую, не стирая старые символы ...
Думаю и пробелы бы меня не спаслиб ...

Короче говоря, Спасибо, что откликнулись - всё пашет как я хотел :)
http://youtu.be/-RW7JUKBo2k
Вложения
MP3_player_forATmega1280.ZIP
Кому интересно, что я мучал - демо исходник "микроя"
(55.1 КБ) 124 скачивания
Последний раз редактировалось RomanT Сб сен 01, 2012 15:13:54, всего редактировалось 1 раз.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Вопрос детский конечно, но я на него ответа не нашел.....

На асме, текст программы делю на несколько загружаемых файлов, например файл настроек, основная программа, файл прерываний и т.д. Додгружаю например так:

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

.include "File_init.inc"
А на С не могу этого сделать, пробовал и

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

#include "File_init.c"
и

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

#include "File_init.h"
чет не получаисся..... Направьте на путь истинный.....
Опытный кот
Аватара пользователя
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону

Сообщение Goldsmith »

Файл File_init.h находится в той же директории, что и главная программа?
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

именно.....
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

"Не получается" - это не объяснение проблемы.
Что значит не получается ? Не получается написать строку #include "File_init.h" ? Тогда Вам необходимо купить новую клавиатуру.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Ах.... да да да да да, пердонн.....
Вот какие ошибки выдает.....
err.png
(41.57 КБ) 338 скачиваний
Файлы лежат в директории, где и основной файл "soldering_power_control.c"
Ответить

Вернуться в «Разные вопросы по МК»