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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
Zhuk72
Сверлит текстолит когтями
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку
Контактная информация:

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

Сообщение Zhuk72 »

Она меняется в другой подпрограмме, но я, когда встал в ступор, специально переде этой процедурой вписал i=0, но результат был тем же.
Тем не менее я проверил, 0 и 2 в другом месте назначаются.
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Реклама
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

В другом месте - это не в прерывании ли, часом?
Если так, то такое поведение может быть результатом оптимизации кода компилятором.
Реклама
Аватара пользователя
Zhuk72
Сверлит текстолит когтями
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку
Контактная информация:

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

Сообщение Zhuk72 »

Не в прерывании. Но я же говорю, что прямо перед этой операцией назначаю, и безрезультатно.
Каждый имеет право на свое личное ошибочное мнение.

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

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

Сообщение ARV »

а так что будет?

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

if ((row < 2) && ((digit == i) || (digit == (i + 1)))) val = 0x10;
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

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

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

Сообщение WiseLord »

Забавы ради проверил на PC:

Изображение

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

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

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

ARV писал(а):а так что будет?

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

if ((row < 2) && ((digit == i) || (digit == (i + 1)))) val = 0x10;
Да всё также и будет. У "+" всяко приоритет выше, чем у "==".

У человека явно проблемы с переменной i. Скорее всего, дело рук оптимизатора. Пусть, для начала, volatile заюзает для переменных.
Реклама
Аватара пользователя
Zhuk72
Сверлит текстолит когтями
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку
Контактная информация:

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

Сообщение Zhuk72 »

Это оптимизация. Отключил ее и проверка начала осуществляться, но при этом прилично вырос код. Я еще вечером игрался с volatile, но результатов никаких.
То, что предлагал ARV, я делал, но его пост напомнил мне о том, что я забыл упомянуть одну вещь: когда digit == i, это всегда исполняется (т.е. когда 0 == 0), но когда digit становится 1, сравнение i+1 обходится стороной.

Раньше это выражение стояло в прерывании и работало, но как только я перенес его в другое место, стало выкидывать такие вот коленца.

Сейчас еще поиграюсь.

P.S. Исследования показали, что в выражении digit == i + 1 компилятор упорно не желает видеть все, что после i. Скобки не помогают. менял местами слагаемые, задавал отдельную переменную , равную 1 и складывал с i. Даже делал (i | 1) в разных комбинациях. Оптимизатор принципиально игнорирует наращивание.

Уже злюсь, со вчерашнего вечера этой фигней маюсь.

P.P.S. РЕШЕНО правой рукой до носа через левое ухо, но хотя бы работает. Оптимизацию не трогал.
Исследования показали, что даже без volatile переменная i до этой операции доходит нормально (0 или 2 в нужные моменты), просто компилятор упорно не желал делать i+1. Кстати, это Кейл. Но я все равно обманул его :)

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

    in = digit + i;  // т.е. in будет равен 0-1 или 4-5.
    if ((row < 2) && ((in < 2) || (in > 3))) val = 0x10;
Всем микрорадиокотам спасибо за поддержку!
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Аватара пользователя
Apparatchik
Держит паяльник хвостом
Сообщения: 908
Зарегистрирован: Вс май 23, 2010 13:55:42
Откуда: Украина, Александрия

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

Сообщение Apparatchik »

Подскажите пожалуйста почему так происходит, контроллер ATmega8 gcc version 4.3.3

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

uint8_t bcd2bin(uint8_t value) {
	return (value / 16) * 10 + (value % 16);
// return (value >> 4) * 10 + (value & 0x0F);
}

int main(void) {
	uint8_t in, out;

	in = PINB;

	out = bcd2bin(in);

	PORTC = out;

	for(;;) {

	}
}
При таком коде занимает 88 байт флеша, если же раскоментировать строку со здвигом и закоментировать с делениями - 104 байта. Если объявить эту функцию как static, то при любом варианте 84 байта. Причем разница в размерах тем больше, чем чаще вызывается эта функция гдето в коде.
«И всё-таки она вертится!»
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

Apparatchik писал(а):почему так происходит
во-первых, у вас 2 разных выражения, отсюда и разный объем при использовании одного и другого:
Apparatchik писал(а):   return (value / 16) * 10 + (value % 16);
// return (value >> 4) * 10 + (value & 0x0F);
во-вторых, если функция объявлена static и используется только в одном месте, она почти со 100% гарантией будет компилятором (оптимизатором) проинлайнена в коде. т.к. в этом случае нет накладных расходов на передачу параметров и возврат результата, это сокращает объем кода.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Apparatchik
Держит паяльник хвостом
Сообщения: 908
Зарегистрирован: Вс май 23, 2010 13:55:42
Откуда: Украина, Александрия

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

Сообщение Apparatchik »

ARV писал(а):во-первых, у вас 2 разных выражения, отсюда и разный объем при использовании одного и другого:
В другом компиляторе (для STM32) эти выражения дают одинаковый по размеру код, вот я и подумал что оптимизатор их должен привести к одному и тому же. Если она static ведь оптимизатор дает одинаковый размер.
«И всё-таки она вертится!»
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

Apparatchik писал(а):вот я и подумал что оптимизатор их должен привести к одному и тому же
неисповедимы пути оптимизатора... смените версию avr-gcc и наверняка сможете получить еще один вариант...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

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

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

Сообщение WiseLord »

Таки да. У меня, например, что деление на 16, что сдвиг на 4 генерирует абсолютно одинаковый ассемблерный код. Причём сдвиг там даже не используется - вместо сдвига на 4 там просто swap байта:
Спойлер

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

uint8_t bcd2bin(uint8_t value)
{
    return (value >> 4) * 10 + (value & 0x0F);
    //return (value / 16) * 10 + (value % 16);
}

mov	r25, r24
swap	r25
andi	r25, 0x0F	; 15
andi	r24, 0x0F	; 15

ldi	r18, 0x0A	; 10
mul	r25, r18
add	r24, r0
eor	r1, r1
ret
Аватара пользователя
Siarzhuk
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

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

Сообщение Siarzhuk »

Apparatchik писал(а):При таком коде занимает 88 байт флеша, если же раскоментировать строку со здвигом и закоментировать с делениями - 104 байта.
А вы сохрание asm выхлоп компилятора для обеих вариантов и сравните в каком-нибудь двухпанельном diff-e - сразу покажет, что там оптимизатор не так понял. Попробуйте сравнить варианты с частями выражения - до '+' и после него.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Аватара пользователя
FeCat
Прорезались зубы
Сообщения: 211
Зарегистрирован: Пт окт 21, 2011 14:39:31

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

Сообщение FeCat »

Можно ли sizeof применять к одной из размерностей массива?
Аватара пользователя
Siarzhuk
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

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

Сообщение Siarzhuk »

FeCat писал(а):Можно ли sizeof применять к одной из размерностей массива?

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

  int aaa[2][3][4] = { 0 };
  int z = sizeof(aaa);
  int z1 = sizeof(aaa[0]);
  int z2 = sizeof(aaa[0][0]);
  int z3 = sizeof(aaa[0][0][0]);
  _tprintf(_T("%d %d %d %d "), z, z1, z2, z3);
96 48 16 4
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

Или, чуть доработав:

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

    int aaa[6][7][8];
    int z0 = sizeof(aaa);
    int z1 = sizeof(aaa[0]);
    int z2 = sizeof(aaa[0][0]);
    int z3 = sizeof(aaa[0][0][0]);

    printf("%d %d %d \n", z0/z1, z1/z2, z2/z3);
6 7 8
Аватара пользователя
Siarzhuk
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

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

Сообщение Siarzhuk »

[quote="WiseLord"]Или, чуть доработав:[/code]
:) Да, совершенству нет предела:

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

 
#ifndef _countof
#define _countof(__a) (sizeof(__a) / sizeof(*__a))
#ednif

_tprintf(_T("%d %d %d"),  _countof(aaa), _countof(aaa[0]), _countof(aaa[0][0]));
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Аватара пользователя
FeCat
Прорезались зубы
Сообщения: 211
Зарегистрирован: Пт окт 21, 2011 14:39:31

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

Сообщение FeCat »

Огромное спасибо!
uk8amk
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

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

Сообщение uk8amk »

Появился не совсем понятный мне момент.
Код:

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

#define     __IO    volatile             /*!< Defines 'read / write' permissions

__INLINE void FlashWord16Prog(uint32_t flash_addr, uint16_t data)
{    
 ...
/* (2) Perform the data write (half-word) at the desired address */
  *(__IO uint16_t*)(flash_addr) = data; /* (2) */
 ...
}
Значение flash_adr приводится к указателю на тип (volatile uint16_t*), затем происходит доступ записи по этому адресу.
Я хочу понять как распутывается эта запись.
Допустим имеем

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

volatile uint16_t *ptr;
*ptr = data;
ptr++;
Что здесь происходит?
а) работа(инкремент) с указателем-переменной как с volatile
б) копирование данных по адресу ptr с отключенной оптимизацией компилятора.
Аватара пользователя
menzoda
Вымогатель припоя
Сообщения: 535
Зарегистрирован: Вт авг 28, 2012 22:21:33

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

Сообщение menzoda »

uk8amk писал(а):Что здесь происходит?
Ничего сложного. Значение data копируется в 16-битную ячейку памяти, на которую указывает ptr. Затем, инкремент смещает указатель так чтобы он указывал на следующую 16-битную ячейку. Ключевое слово volatile гарантирует, что запись в ячейку произойдет именно в этом месте (это так, по простому).
Ответить

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