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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
vash_sa
Открыл глаза
Сообщения: 50
Зарегистрирован: Чт сен 04, 2014 13:22:44

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

Сообщение vash_sa »

Подскажите, пожалуйста, как из массива uint16_t получить массив uint8_t. Наоборот знаю. Необходимо, чтобы значения переменных не были искажены.
Спасибо!
Реклама
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18561
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

интересно, как без искажений вы впихнете в uint8_t значение, например, 2096, которое легко помещается в uint16_t?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Реклама
vash_sa
Открыл глаза
Сообщения: 50
Зарегистрирован: Чт сен 04, 2014 13:22:44

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

Сообщение vash_sa »

Мне надо разделить байты в 2 байтовом числе. Как это сделать?
Аватара пользователя
uldemir
Друг Кота
Сообщения: 7359
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

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

Сообщение uldemir »

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

low = input & 0x00FF;
high = (input >> 8) & 0x00FF;
подразумевается low, high - uint8, input uint16
или надо что-либо более адванснутое?
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18561
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

задача поставлена слишком туманно, вариантов море:

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

// первый вариант: получаем массив байтов из массива int-ов
uint16_t source_array[SIZE]; // исходный массив
uint8_t *dest_array = (void*)source_array; // объявляем указатель на байт

uint8_t tmp = dest_array[10]; // извлекаем 11-й байт из исходного массива

// второй вариант: переделываем массив, оставляя только младшие байты из исходного массива
uint8_t dest_array[SIZE]; // объявляем результирующий массив
// в цикле заполняем массив
for(uint8_t i=0; i<SIZE; i++)
   dest_array[i] = source_array[i];

// третий вариант - то же, что и второй, но берем старший байт
for(uint8_t i=0; i<SIZE; i++)
   dest_array[i] = source_array[i] >> 8;
ну и дальше в рамках фантазии аналогично...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Реклама
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18561
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

uldemir писал(а):

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

low = input & 0x00FF;
high = (input >> 8) & 0x00FF;
подразумевается low, high - uint8, input uint16
или надо что-либо более адванснутое?
избыточно, хватило бы и просто

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

low = input;
high = input >> 8;
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Реклама
Аватара пользователя
uldemir
Друг Кота
Сообщения: 7359
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

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

Сообщение uldemir »

перестраховался на случай, если вздумает 32-х битное подсунуть :))
vash_sa
Открыл глаза
Сообщения: 50
Зарегистрирован: Чт сен 04, 2014 13:22:44

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

Сообщение vash_sa »

Огромное спасибо!
vash_sa
Открыл глаза
Сообщения: 50
Зарегистрирован: Чт сен 04, 2014 13:22:44

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

Сообщение vash_sa »

Помогите еще разок. Теперь есть массив из uint8_t первый байт младший, второй старший. Как наиболее эффективно сделать массив uitn16_t?

Спасибо!
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

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

typedef union {
  uint8_t arr8[10];
  uint16_t arr16[5];
} myType;

int main() {
  myType x;
  uint16_t a;

  x.arr8[0] = 0x34;
  x.arr8[1] = 0x57;

  a = x.arr16[0]; // a присвоили значение 0x5734;
}
Все сдвиги и прочее берёт на себя компилятор. Память у массивов arr8 и arr16 общая.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18561
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

самый эффективный способ из массива байтов получить массив int-ов (при условии, что байты расположены в правильном порядке - младший-старший), это использовать указатель, я уже писал об этом:

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

uint8_t source[SIZE]; // исходный массив байтов
uint16_t *dest = (void*)source; // новый массив
работать с таким указателем точно так же, как с массивом: dest - будет число из пары байт исходного массива. не ошибитесь только с индексацией - в новом массиве будет в 2 раза меньше элементов...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
vash_sa
Открыл глаза
Сообщения: 50
Зарегистрирован: Чт сен 04, 2014 13:22:44

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

Сообщение vash_sa »

Еще раз огромное спасибо!
Аватара пользователя
menzoda
Вымогатель припоя
Сообщения: 535
Зарегистрирован: Вт авг 28, 2012 22:21:33

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

Сообщение menzoda »

ARV писал(а):самый эффективный способ из массива байтов получить массив int-ов (при условии, что байты расположены в правильном порядке - младший-старший), это использовать указатель
Не не не. А как же выравнивание адресов? Некоторые архитектуры могут работать только с данными, выровненными по адресу, кратному размеру данных (или большей степени двойки). То есть, чтобы прочитать/записать в int16, это значение должно располагаться в памяти по адресу, кратному хотя бы двум, если нужно прочитать/записать int32, то оно должно располагаться по адресу, кратному хотя бы четырем, и так далее.

Массив байтов может быть расположен по любому адресу. Приведя его указатель к указателю на массив двухбайтных значений можно нарушить требование выравнивания. Конечно, это не обязательно приведет к ошибке, возможно просто снизиться производительность, или даже ничего не случиться. Тем не менее такое решение довольно опасно и непереносимо.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18561
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

menzoda писал(а):
ARV писал(а):самый эффективный способ из массива байтов получить массив int-ов (при условии, что байты расположены в правильном порядке - младший-старший), это использовать указатель
Не не не.
да да да :) поскольку речь идет об AVR, то рассуждения о выравнивании - это притянуто за уши. и порядок байтов в int тоже. о какой переносимости может идти речь, если embedded-avr-программы на 90% состоят из аппаратно-зависимых (т.е. по определению непереносимых) действий?!

теория - это сила, но совать ее бесконтрольно в практику - только мешать :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
ks0
Прорезались зубы
Сообщения: 238
Зарегистрирован: Чт фев 28, 2013 14:16:10

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

Сообщение ks0 »

Да и на 32-битных не приведет к ошибке, выравнивание, не выравнивание, это забота компилятора. Сказали второй байт, значит второй байт.
Аватара пользователя
menzoda
Вымогатель припоя
Сообщения: 535
Зарегистрирован: Вт авг 28, 2012 22:21:33

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

Сообщение menzoda »

ks0 писал(а):это забота компилятора. Сказали второй байт, значит второй байт.
Компилятор конечно может обернуть работу с невыравненными данными в несколько дополнительных команд, но тогда мы заметно потеряем в производительности. Вот только я не уверен, что он обязан это делать, нужно читать стандарт и документацию на конкретный компилятор. Скорее всего в стандарте как всегда будет undefined behavior или implementation defined. Так что все-равно нужно включать голову и писать переносимый код.
ARV писал(а):о какой переносимости может идти речь, если embedded-avr-программы на 90% состоят из аппаратно-зависимых (т.е. по определению непереносимых) действий?!
А почему у меня программы не состоят на 90% из аппаратно-зависимых действий? Просто нужно минимизировать и отделять аппаратно-зависимый код от всего остального, и не плодить костыли да хаки там, где это не нужно. А это как раз тот случай, где их можно избежать.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18561
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

menzoda писал(а):А почему у меня программы не состоят на 90% из аппаратно-зависимых действий?
я не виноват, что вам не повезло... :dont_know:
:)))
90% avr-овских проектов - это дрыгоножество и настройка периферии. если ваши проекты считают разложения Лагранжа - там будет 99% переносимого кода...

в сущности, спор бесполезен, истина где-то рядом...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
ks0
Прорезались зубы
Сообщения: 238
Зарегистрирован: Чт фев 28, 2013 14:16:10

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

Сообщение ks0 »

menzoda писал(а):Компилятор конечно может обернуть работу с невыравненными данными в несколько дополнительных команд, но тогда мы заметно потеряем в производительности. Вот только я не уверен, что он обязан это делать, нужно читать стандарт и документацию на конкретный компилятор. Скорее всего в стандарте как всегда будет undefined behavior или implementation defined.
Прикольно, представил себе почти все функции обработки строк char* оказываются undefined behavior!
Аватара пользователя
ks0
Прорезались зубы
Сообщения: 238
Зарегистрирован: Чт фев 28, 2013 14:16:10

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

Сообщение ks0 »

Че-то у меня лыжи не едут при попытки хранить строки во флеш. AVR GCC, пишу так

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

#include <avr/io.h>
#include <avr/pgmspace.h>
const char* s PROGMEM = "Text";
void main()
{
	char c[20]; // буфер
	strcpy_P(c,s);
}
И вижу, что отладчик пишит, что во флеш по адресу 0х54 хранится число 0х60, которое есть указатель на адрес в ОЗУ, где и хранится сам текст, текст действительно там и оказывается. В буфер нефига вразумительного не копируется.
Че за фигня?! Т.е. во флеше только указатель, а сами данные в ОЗУ!
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18561
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

прочтите о том, как правильно размещать строки во флеш при использовании старых версий AVR GCC. вы допустили ошибку - вы разместили во флеш указатель, е строка у вас окажется в ОЗУ. зачем вам флешевый указатель на ОЗУ? правильно так:

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

PROGMEM char str[] = "Что-то там";
sprcpy_P(s, str);
Однако, во множестве случаев может быть гораздо удобнее использование макроса PSTR:

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

strcpy_P(s, PSTR("Что-то там"));
то есть можно задавать константные строки в таком виде, если более не потребуются адреса этих строк.

однако, в настоящее время WinAVR уже можно считать устаревшим компилятором, более свежие версии AVR GCC, а так же AVR Toolchain от Atmel уже поддерживают префикс __flash для определения констант в памяти программ, при этом работа с ними происходит прозрачно для большинства применений, т.е. уже не надо использовать функции с суффиксом _P или специальные средства типа pgm_read_byte
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Ответить

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