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

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

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

Сообщение vitalik_1984 »

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

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

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

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

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

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

Сообщение 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)));
абсолютно идентичны.
Только недавно об этом писал... viewtopic.php?p=1380428#p1380428
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

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

Сообщение 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
Аватара пользователя
urry
Сверлит текстолит когтями
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница
Контактная информация:

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

Сообщение 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); будет выполняться правильно.
Насколько я отступаю от стандарта в этом случае - пока катастроф не видел.
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

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

Сообщение ploop »

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

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

Сообщение 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), иногда такое встречал в чужом коде, но в чём кайф -- не понимаю.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

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

Сообщение Goldsmith »

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

Началось в эпической теме про счетчики, переодетые сдвиговыми регистрами, и с тех пор который раз уже...

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

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

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

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

Сообщение 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:
В поисках истины человек развивается.
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

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

Сообщение 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
Аватара пользователя
RomanT
Это не хвост, это антенна
Сообщения: 1335
Зарегистрирован: Ср июн 09, 2010 16:44:54
Откуда: Пермь
Контактная информация:

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

Сообщение 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++ в конце цикла-же ...
Tolmi
Говорящий с текстолитом
Сообщения: 1658
Зарегистрирован: Вс дек 11, 2011 05:25:04
Откуда: Киев, Украина
Контактная информация:

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

Сообщение Tolmi »

Первый класс, вторая четверть. "Мама мыла раму"...

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

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

Сообщение RomanT »

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

----------

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

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

Сообщение Tolmi »

RomanT писал(а):Ну уж извините ... первый раз сел за Си ...

Ну, кроме бэйсика я уж и не припомню языков, в которых индексы массива по умолчанию не начинались с нуля. В МС бэйсике, кстати, для этого тоже рукоятка для управления есть.
Ещё вопрос, как в char переменной написать несколько пробелов ?

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

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

Сообщение 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 раз.
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

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

Сообщение shads »

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

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

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

.include "File_init.inc"


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

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

#include "File_init.c"
и

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

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

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

Сообщение Goldsmith »

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

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

Сообщение shads »

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

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

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

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

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

Сообщение shads »

Ах.... да да да да да, пердонн.....
Вот какие ошибки выдает.....

err.png
(41.57 КБ) 338 скачиваний

Файлы лежат в директории, где и основной файл "soldering_power_control.c"
Ответить

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