Странное поведение при добавлении лонгов в RobotC

Это пример проблемы, с которой я сталкиваюсь в RobotC 3.62:

long heading;
task main()
{
    long num = 0;
    heading=num+90000;
}

Это дает результат heading=24464, чего я не ожидал.

Я попытался заменить часть 90000 длинной, содержащей 90000, и это дало ожидаемый результат. Кажется, что запись числа 90000 вызывает какую-то ошибку переполнения (90000-256^2=24464). Это странно, так как long должен содержать «целое число в диапазоне от -2 147 483 648 до 2 147 483 647». Нужно ли мне его как-то кастрировать? Я не знаком с C, может ли кто-нибудь объяснить это поведение? Спасибо!


person mrmprog    schedule 14.01.2015    source источник
comment
Это определенно звучит так, как будто он хранит его как 16-битное целое число вместо 32-битного. В документации на их сайте говорится, что типы данных long, float и string не поддерживаются на платформах Arduino 328. Но я вижу, что вы установили тег NXT, так что я предполагаю, что это не применимо. Это может быть ошибка компилятора — я помню, что у компилятора NQC были всевозможные странные проблемы, когда я программировал Mindstorms. Вы уже обращались к поставщику за поддержкой? Поскольку это стоит денег, я ожидаю, что они предоставят разумную поддержку.   -  person Katie    schedule 14.01.2015
comment
Да, я на NXT Mindstorm для соревнований по робототехнике. Кажется, я могу обойти это, сначала сохранив число в длинном, но это раздражающее решение проблемы, которая (насколько я могу судить) не должна существовать. Я попробую связаться с ними и посмотреть, могу ли я получить какую-либо помощь. Спасибо, есть другие предложения?   -  person mrmprog    schedule 14.01.2015
comment
Не совсем - лучшее, что я могу предложить, - это использовать несколько разных способов представления проблемы и надеяться, что один из них скомпилируется правильно. Задайте константу в шестнадцатеричном виде или в виде (длинного) 90000 или сложите ее порциями, все из которых составляют 32 768 или меньше.   -  person Katie    schedule 14.01.2015
comment
У вас есть доступ к stdint.h? У него есть typedef, например int32_t, и defines, например INT32_MAX.   -  person Fiddling Bits    schedule 14.01.2015
comment
Похоже, этот компилятор просто ужасно сломан   -  person M.M    schedule 14.01.2015


Ответы (2)


Это известная проблема в версии 3.X, которая ранее была исправлена ​​в версии 4.X и устранена в текущем общедоступном выпуске версии 4.X. Однако для 3.x есть обходной путь.

С предоставленным вами кодом вывод компилятора усекает результат, выполняя только целочисленные вычисления. Это была обнаруженная ранее ошибка, которая позже была исправлена, но все еще существует в более старых версиях... вот вывод:

long num = 0;
0025: CB000000 num:S00(slong) = 0 // long/float
heading = num + 90000;
0029: BD0800002B000000905F heading:G00(slong) = num:S00(slong) + 90000

В качестве обходного пути в 3.X, если вы рассматриваете константу как «плавающую», указав 90000.0, компилятор сгенерирует код, который не будет усекать long, потому что он будет выполнять 32-битные математические операции (на NXT «int " на самом деле короткие целые числа, отсюда и усечение)

long num = 0;
0025: CB000000 num:S00(slong) = 0 // long/float
heading = num + 90000.0;
0029: AD2D04002B0000 S04(float) = num:S00(slong) // Store in temp variable :: Convert 'long' to 'float'
0030: 902D040000C8AF47 S04(float) += 90000 // Perform <op> on temp variable :: float
0038: 8C0800002D0400 heading:G00(slong) = S04(float) // Convert 'float' to 'long'
person tfriez    schedule 14.01.2015

Попробуйте сделать 90000 длинным, например: 90000L.

long heading;
task main()
{
    long num = 0;
    heading = num + 90000L;
}
person DigitalRoss    schedule 14.01.2015
comment
Спасибо за ответ! Однако я попробовал это, и код не скомпилировался. **Error**:Expected->';'. Found 'L' **Error**:Undefined variable 'L'. 'short' assumed. *Warning*:Meaningless statement -- no code generated - person mrmprog; 14.01.2015
comment
Хм, на самом деле вам не нужен L в соответствующих версиях современного C — предполагается использовать наименьший тип, который работает для значения. Похоже, вам нужен ответ, специфичный для RobotC, и держу пари, что это будет: извините, long не поддерживается. Вы можете проверить это с помощью чего-то вроде int f(int a,int b){return a+b;}, затем: посмотрите на сгенерированный код, измените все int в long, а затем посмотрите, изменится ли сгенерированный код. Или просто посмотрите в документах. - person DigitalRoss; 14.01.2015
comment
соответствующие версии современного C, т. е. не RobotC - person qxz; 22.09.2016