Программирование С баг компилятора ? (только 8 и 16 р МК)

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Потрогал лапой паяльник
Сообщения: 390
Зарегистрирован: Чт сен 24, 2009 17:22:51
Откуда: UK

Сообщение FUZZY_ »

#define LK 0x7FFF
#define SIZELINE 40
#define PY LK/SIZELINE
#define KV LK/PY

Баг находится в четвертой строчке . Кто может обяснить этот баг.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3961
Зарегистрирован: Пн июл 13, 2009 14:37:39
Откуда: Московская область, наукоград.....

Сообщение Meteor »

Если правильно понимаю, то препроцессор вычисляет
PY = LK/SIZELINE= 0x7FFF/40, затем пытается найти
KV = LK/PY = LK/LK/SIZELINE=SIZELINE
это его наверное и сводит с ума...
Или тут была какая то другая стратегическая идея??
Загружая на вход компьютера "мусор", на выходе получим "мусор^32".
PS. Не работаю с: Proteus, Multisim, EWB, Micro-Cap... не спрашивайте даже
Контактная информация:
Реклама
Опытный кот
Аватара пользователя
Сообщения: 890
Зарегистрирован: Вт янв 20, 2009 14:49:08
Откуда: Гондурас, Мурманск

Сообщение DrWatson »

не, препроцессор посчитает LK/LK/SIZELINE=0!!!
те сначала LK/LK=1 потом 1/SIZELINE=0
заимей привычку математические выражения в директивах #define всегда заключать в скобки:

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

#define LK 0x7FFF 
#define SIZELINE 40 
#define PY (LK/SIZELINE) 
#define KV (LK/PY)
Вот здесь он посчитает как надо, т.е. KV=SIZELINE
Так что дело было не в бобине :))
ЗЫ: "баг" такой скорее всего будет в любом компиляторе С.
ЗЗЫ: в любом нормальном учебнике по Си настоятельно рекомендуется пользоваться а таких случаях скобками.
- Если вы такие умные, то почему тогда строем не ходите?
ἓν οἶδα ὅτι οὐδὲν οἶδα (с) Σωκράτης
Потрогал лапой паяльник
Сообщения: 390
Зарегистрирован: Чт сен 24, 2009 17:22:51
Откуда: UK

Сообщение FUZZY_ »

DrWatson писал(а):не, препроцессор посчитает LK/LK/SIZELINE=0!!!
те сначала LK/LK=1 потом 1/SIZELINE=0
заимей привычку математические выражения в директивах #define всегда заключать в скобки:

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

#define LK 0x7FFF 
#define SIZELINE 40 
#define PY (LK/SIZELINE) 
#define KV (LK/PY)
Вот здесь он посчитает как надо, т.е. KV=SIZELINE
Так что дело было не в бобине :))
ЗЫ: "баг" такой скорее всего будет в любом компиляторе С.
ЗЗЫ: в любом нормальном учебнике по Си настоятельно рекомендуется пользоваться а таких случаях скобками.
Насчет скобок правильно но не точно, а надо:
#define LK 0x7FFF
#define SIZELINE 40
#define PY LK/SIZELINE //тут вычисление идет правильно
//или так #define PY (LK/SIZELINE) // результат тот-же
#define KV (LK)/(PY) ( при #define KV (LK/PY) KV=0.) но это только для 8 и 16 р компиляторов
для 32 р все работает и без ксобок
Реклама
Эиком - электронные компоненты и радиодетали
Встал на лапы
Аватара пользователя
Сообщения: 130
Зарегистрирован: Пн авг 24, 2009 10:41:16
Откуда: SPb

Сообщение testerplus »

FUZZY_ писал(а):Насчет скобок правильно но не точно,
DrWatson как раз написал все правильно и точно, а у Вас до сих пор осталась неточность:
а надо:
#define LK 0x7FFF
#define SIZELINE 40
#define PY LK/SIZELINE //тут вычисление идет правильно
//или так #define PY (LK/SIZELINE) // результат тот-же
#define KV (LK)/(PY) ( при #define KV (LK/PY) KV=0.)
в выделенном тексте: в общем случае LK и SIZELINE могут также быть выражениями, поэтому их по Вашему методу также придется брать в скобки (LK)/(SIZELINE). (Через полгода Вам придется изменить программу так, чтобы SIZELINE было выражением от каких-то параметров - и все посыпется, а Вы будете еще долго думать, что за фигня)

Но брать в скобки каждый операнд - запарно (сейчас выражения простые, а бывают по десятку действий, и из-за скобок выражение потеряет наглядность), поэтому везде рекомендуют в скобки заключать все выражение при дефайне.
но это только для 8 и 16 р компиляторов
для 32 р все работает и без ксобок
Разрядность тут не при чем. Это скорее особенность какой-то конкретной реаизации компилятора; кстати, очень редкая особенность и, скорее, это даже ошибка (если Вы сами не ошиблись), поскольку define - это директива компилятору, он выполняет подстановку текста, а не вычисление выражений, поэтому в получившемся выражении LK/LK/SIZELINE действия, имеющие одинаковый приоритет, должны выполняться последовательно слева направо.
Контактная информация:
Реклама
Потрогал лапой паяльник
Сообщения: 390
Зарегистрирован: Чт сен 24, 2009 17:22:51
Откуда: UK

Сообщение FUZZY_ »

testerplus писал(а):
FUZZY_ писал(а):Насчет скобок правильно но не точно,
DrWatson как раз написал все правильно и точно, а у Вас до сих пор осталась неточность:
а надо:
#define LK 0x7FFF
#define SIZELINE 40
#define PY LK/SIZELINE //тут вычисление идет правильно
//или так #define PY (LK/SIZELINE) // результат тот-же
#define KV (LK)/(PY) ( при #define KV (LK/PY) KV=0.)
в выделенном тексте: в общем случае LK и SIZELINE могут также быть выражениями, поэтому их по Вашему методу также придется брать в скобки (LK)/(SIZELINE). (Через полгода Вам придется изменить программу так, чтобы SIZELINE было выражением от каких-то
параметров - и все посыпется, а Вы будете еще долго думать, что за фигня)

Но брать в скобки каждый операнд - запарно (сейчас выражения простые, а бывают по десятку действий, и из-за скобок выражение потеряет наглядность), поэтому везде рекомендуют в скобки заключать все выражение при дефайне.
но это только для 8 и 16 р компиляторов
для 32 р все работает и без ксобок
Разрядность тут не при чем. Это скорее особенность какой-то конкретной реаизации компилятора; кстати, очень редкая особенность и, скорее, это даже ошибка (если Вы сами не ошиблись), поскольку define - это директива компилятору, он выполняет подстановку текста, а не вычисление выражений, поэтому в получившемся выражении LK/LK/SIZELINE действия, имеющие одинаковый приоритет, должны выполняться последовательно слева направо.
Проверено 4 (16 р) компилятора 3 -для МК (разные платформы ) , 1 - для РС
Проверено 2 ( 32 р) компилятора GNU, Borlad - PC
С вышесказанным об особенностях компиляторов не согласен
(Нет программы без ошибок, постосто ошибки по разному проявляются !)
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 130
Зарегистрирован: Пн авг 24, 2009 10:41:16
Откуда: SPb

Сообщение testerplus »

FUZZY_ писал(а):Проверено 4 (16 р) компилятора 3 -для МК (разные платформы ) , 1 - для РС
Проверено 2 ( 32 р) компилятора GNU, Borlad - PC
С вышесказанным об особенностях компиляторов не согласен
(Нет программы без ошибок, постосто ошибки по разному проявляются !)
Насчет "особенности" я погорячился. Это была бы не особенность, а ошибка. Директива define не делает вычислений. На место определеляемых идентификаторов подставляется текст определения (а не результат выражения). Компилятором идентификатор KV будет рассмотриваться как LK/LK/SIZELINE.

В мануале Borland C++ в параграфе "Associativity and Precedence of Operators" указано, что операторы "/" в одном выражении выполняются слева направо (если они не прерыванются операторами других приоритетов). А в мануале на MSVC++ к такому же определению есть еще приписка: "An expression can contain several operators with equal precedence. When several such operators appear at the same level in an expression, evaluation proceeds according to the associativity of the operator, either from right to left or from left to right."
FUZZY_ писал(а):для 32 р все работает и без ксобок

Кстати, как Вы проверяли? Вот три программы, которые собирались под 32-битными компиляторами. Во всех переменная A после присваивания стала равна 0.

Borland C++:

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

//---------------------------------------------------------------------------

#include <vcl>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

#define LK       0x7FFF
#define SIZELINE 40
#define PY       LK/SIZELINE
#define KV       LK/PY

unsigned long A;

void __fastcall TForm1::FormCreate(TObject *Sender)
{
     A = KV;
}
MS Visual C++:

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

#define LK       0x7FFF
#define SIZELINE 40
#define PY       LK/SIZELINE
#define KV       LK/PY

unsigned long A;

void main (void)
{
     A = KV;
}
MPLAB C32 (GNU):

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

#define LK       0x7FFF
#define SIZELINE 40
#define PY       LK/SIZELINE
#define KV       LK/PY

unsigned long A;

void main (void)
{
     A = KV;
}
Контактная информация:
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

Виктор, Вы меня удивляете... :) Столько телодвижений, чтобы доказать, что 2+2=4
Я фсе время думал, ну если у них такой ТЕСТЕР, то какие же там программеры, ну вообще звери наверное - рвут на части одним взглядом...
Потом думаю, ну - нет там ложки... как в матрице - нет этих сверхинтеллектуальных программеров - я так честно их в свое время пытался искать ...
Вот - разделите мой пессимизм - имхо, Вы там за них все пишете ?
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 130
Зарегистрирован: Пн авг 24, 2009 10:41:16
Откуда: SPb

Сообщение testerplus »

urry писал(а):Виктор, Вы меня удивляете... :) Столько телодвижений, чтобы доказать, что 2+2=4
Увлекся. :)
urry писал(а):Я фсе время думал, ну если у них такой ТЕСТЕР, то какие же там программеры, ну вообще звери наверное - рвут на части одним взглядом...
Потом думаю, ну - нет там ложки... как в матрице - нет этих сверхинтеллектуальных программеров - я так честно их в свое время пытался искать ...
Вот - разделите мой пессимизм - имхо, Вы там за них все пишете ?
Если бы у меня были мегапрограммеры, то тестер был бы им не нужен. Но вера в их существование осталась.
А сам я ничего не пишу, только правлю или показываю пальцем, где плохо.
Контактная информация:
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»