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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
Kavka
Мудрый кот
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

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

Сообщение Kavka »

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

 addr &= (~3);

Можно так, но фишка была в точке с запятой. :)
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Аватара пользователя
Твори бобро
Родился
Сообщения: 18
Зарегистрирован: Чт дек 27, 2012 05:24:10

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

Сообщение Твори бобро »

Kavka писал(а):

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

 addr &= (~3);

Можно так, но фишка была в точке с запятой. :)

Не, компилятор не принимает операторы типа "&=" и подобные, но по отдельности запросто. Я так понял что "~3" это тупо выравнивание на 4 байта; и фишка не в точке с запятой(просто я руками набирал по памяти :))) ) ;
Аватара пользователя
Твори бобро
Родился
Сообщения: 18
Зарегистрирован: Чт дек 27, 2012 05:24:10

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

Сообщение Твори бобро »

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

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

Сообщение vitalik_1984 »

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

 (addr ~)  
и какой же результат у этого выражения?
может все таки вот так?

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

addr =(~)& addr;  
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

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

Сообщение ibiza11 »

Твори бобро писал(а):Я так понял что "~3" это тупо выравнивание на 4 байта;
.....
надо сбросить 3 младших бита, тем самым получим выравнивание адреса на 32 бита.
почему 3 бита? причем здесь выравнивание? :shock:
"~3" - это константа равная 0xFFFFFFFC (с учетом приведения к типу int для ARM7 переменной addr)
при выполнении операции

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

addr &=~3;
сбрасываются 2 последних бита переменной addr;
Ставим плюсы: )
Cheba
Мучитель микросхем
Сообщения: 447
Зарегистрирован: Ср сен 26, 2012 14:12:47
Откуда: Київ

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

Сообщение Cheba »

Всё правильно, это выравнивание на границу 32-битного слова. Некоторые операции требуют такого выравнивания.
Аватара пользователя
Твори бобро
Родился
Сообщения: 18
Зарегистрирован: Чт дек 27, 2012 05:24:10

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

Сообщение Твори бобро »

vitalik_1984 писал(а):

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

 (addr ~3 )   
и какой же результат у этого выражения?
может все таки вот так?

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

addr =(~3)&addr; 

Ага именно так в итоге и сделал.

ibiza11 писал(а):почему 3 бита? причем здесь выравнивание?

Очепятался. Просто запутался три два два три, и в итоге в голове получилась каша.

Cheba писал(а):Всё правильно, это выравнивание на границу 32-битного слова. Некоторые операции требуют такого выравнивания.

Операция чтения\записи памяти. Т.е addr по любому будет кратен 4-ём. Вообще это какая-то заказная ПЛИСка которая опрашивает другие 32шт ПЛИС. У этих других ПЛИСок по мегабайту RAM и ROM, в общем 32-ух битном адресном пространстве, и все "общение" друг с другом происходит через RAM. Сколково блин :)))

Вообщем прошилось и кажется работает.
igorka
Грызет канифоль
Сообщения: 260
Зарегистрирован: Вс ноя 13, 2011 11:21:23
Откуда: Горловка.

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

Сообщение igorka »

Подскажите пожалуйста ,что обозначают эти две строки :
trisa = trisa & 0xf0;
porta = (porta & 0xf0) | (~FCV_SHOW_DIGIT & 0x0f);
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

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

Сообщение Goldsmith »

1. В младшем байте переменной trisa 4 старших бита остаются неизменными, 4 младших бита сбрасываются в 0. Если разрядность trisa > 8, старшие биты обнуляются.

2. В младшем байте переменной porta 4 старших бита остаются неизменными, 4 младших бита копируют инвертированные 4 младших бита FCV_SHOW_DIGIT. Если разрядность porta > 8, старшие биты обнуляются.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

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

Сообщение vitalik_1984 »

это правильно с точки зрения программы, а с точки зрения действий Мк это значит
1. устанавливаем младшие четыре бита порта А на выход, старшие на вход.(если разрядность больше 8 остальные тоже на выход.)
2. выводим в младшие 4 разряда порта А нужную информацию.Старшие оставляем нетронутыми.(если больше 8 то остальные стбрасываем в 0)
igorka
Грызет канифоль
Сообщения: 260
Зарегистрирован: Вс ноя 13, 2011 11:21:23
Откуда: Горловка.

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

Сообщение igorka »

Спасибо всем кто ответил.И еще маленький вопрос , если позволите.
DDRD = DDRD | 0x30;
PORTD = (PORTD & 0xCF) | (255);
Этим кодом управляю катодом семисегментника напрямую с порта , а мне необходимо его инвертировать , т.е. в порт посылать не "0" а "1" .Что необходимо изменить?
Извините за тупые вопросы , самому стыдно.Может посоветуете книжечку почитать по "СИ" для микроконтроллеров (читаю книгу Керниган.Ричи.Но не то пальто ,ориентируется для другого , учится на ней трудновато)
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

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

Сообщение Goldsmith »

igorka писал(а):PORTD = (PORTD & 0xCF) | (255);
В этой строке переменной PORTD всегда будет присваиваться значение 255 (двоичное 11111111) независимо от того, каким было прежнее значение переменной и с какой константой перед этим выполнялась операция "побитовое И". Результат операции "ИЛИ", когда один из операндов равен 1, всегда 1, независимо от значения второго операнда. Вряд ли это именно то, что Вам нужно в данном случае.

Поэтому на вопрос
igorka писал(а):Этим кодом управляю катодом семисегментника напрямую с порта , а мне необходимо его инвертировать , т.е. в порт посылать не "0" а "1" .Что необходимо изменить?
ответ: всё. Опишите словами, что именно нужно сделать, и я покажу, как это сделать.

Если я вдруг угадал и Вы намеревались вывести инвертированную константу 0xCF в порт, то это делается так:

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

PORTD = ~ 0xCF;
Если не угадал, тогда напишите подробнее, что имелось в виду.

igorka писал(а):Может посоветуете книжечку почитать по "СИ" для микроконтроллеров (читаю книгу Керниган.Ричи.Но не то пальто ,ориентируется для другого , учится на ней трудновато)
Именно эти вопросы очень хорошо описаны у Кернигана-Ритчи (хоть книга и не ориентирована на специфику микроконтроллеров, но в данном случае этой специфики нет, обычная побитовая логика). Может, есть буквари и попроще, но первоисточник все равно предпочтительнее.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Аватара пользователя
Psych
Опытный кот
Сообщения: 848
Зарегистрирован: Ср мар 02, 2011 07:47:39
Откуда: Уфа

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

Сообщение Psych »

Народ...значение функции по-умолчанию доступна только в С++??
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

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

Сообщение ibiza11 »

Да. только в С++
Ставим плюсы: )
Аватара пользователя
Psych
Опытный кот
Сообщения: 848
Зарегистрирован: Ср мар 02, 2011 07:47:39
Откуда: Уфа

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

Сообщение Psych »

Ставим плюсы: )

Поставил :))
Аватара пользователя
baron_P
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Вт сен 14, 2010 23:07:10
Откуда: Ростов

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

Сообщение baron_P »

Приветствую, господа.
Начал ковыряться в AVR и ихнем С, появились глупые вопросы.
Ниже код, выдающий 0 на случайные выхода со случайной задержкой на МК attiny13a.
Спойлер

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

#include<avr/io.h>
#define F_CPU 1200000UL
#include<util/delay.h>
int main(void)
{
 unsigned long lfsr = 1;
 unsigned char temp;
 DDRB = 0xff;
 while(1)
 {
  lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u);
  temp = (unsigned char) lfsr;
  DDRB = ~temp;
  PORTB = temp;
  temp = (unsigned char) (lfsr >> 24);
  _delay_loop_2(temp<<7);
 }
}

Вопроса два.
1. После

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

unsigned long lfsr = 1;
значение переменной в двоичном виде будет 31 ноль и единица в младшем разряде.
Значением этого

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

lfsr >> 1
будет 32 нуля в двоичном виде.
Это

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

lfsr & 1u
приводится к виду (31 ноль и единица в младшем разряде) & (31 ноль и единица в младшем разряде), а результатом будет те же 31 ноль и единица в младшем разряде.
Дальше делается это

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

-(lfsr & 1u)
, т.е. беззнаковое 32-х битное число меняет знак. При этом просто инвертируется старший бит, а тип полученного числа остается unsigned long?
2. Что является аргументом для _delay_loop_2()? Это задержка в каких то долях от тактовой частоты?

Сори за побитовое разжевывание и общий уровень вопросов, только начал вникать, хочу знать правильно ли понимаю логику работы этого дела.
We do what we must because we can (c) GLaDOS
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

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

Сообщение Goldsmith »

baron_P писал(а):Дальше делается это

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

-(lfsr & 1u)
, т.е. беззнаковое 32-х битное число меняет знак.
Не все так просто (уже сама фраза "беззнаковое число меняет знак" должна насторожить).

Знаковое 32-битное число имеет диапазон значений от -2^31 до (2^31) - 1. Беззнаковое 32-битное число имеет диапазон значений от 0 до (2^32) - 1. Очевидно, что значения >= 2^31 не могут быть представлены знаковым 32-битным числом, поэтому при попытке такой смены знака компилятор должен выдать как минимум предупреждение.

baron_P писал(а):При этом просто инвертируется старший бит, а тип полученного числа остается unsigned long?
Зависит от реализации. Например, стандарт ISO/IEC 9899:1999 в п. 6.2.6.2 Integer types предлагает следующие варианты представления отрицательных величин:

2. For signed integer types, the bits of the object representation shall be divided into three groups: value bits, padding bits, and the sign bit. There need not be any padding bits; there shall be exactly one sign bit. Each bit that is a value bit shall have the same value as the same bit in the object representation of the corresponding unsigned type (if there are M value bits in the signed type and N in the unsigned type, then M <= N). If the sign bit is zero, it shall not affect the resulting value. If the sign bit is one, the value shall be modified in one of the following ways:
— the corresponding value with sign bit 0 is negated (sign and magnitude);
— the sign bit has the value -(2N) (two’s complement);
— the sign bit has the value -(2N - 1) (one’s complement).
Which of these applies is implementation-defined, as is whether the value with sign bit 1 and all value bits zero (for the first two), or with sign bit and all value bits 1 (for one’s complement), is a trap representation or a normal value. In the case of sign and magnitude and one’s complement, if this representation is a normal value it is called a negative zero.
В данном случае сам кристалл (и соответственно "ихний C" (C), предположительно WinAVR) поддерживает "дополнение до двух", но лучше все-таки не закладываться на особенности реализации вроде поразрядного представления чисел и/или endianness. Для этой задачи найдется способ решения гораздо корректнее, если сформулирете, что именно хотели получить (инверсию старшего бита?).

baron_P писал(а):2. Что является аргументом для _delay_loop_2()? Это задержка в каких то долях от тактовой частоты?
А это уже называется лень-матушка:

22.28.2.2 void _delay_loop_2 (uint16_t __count)
Delay loop using a 16-bit counter __count, so up to 65536 iterations are possible. (The value 65536 would have to be passed as 0.) The loop executes four CPU cycles per iteration, not including the overhead the compiler requires to setup the counter register pair.

Thus, at a CPU speed of 1 MHz, delays of up to about 262.1 milliseconds can be achieved.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Аватара пользователя
baron_P
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Вт сен 14, 2010 23:07:10
Откуда: Ростов

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

Сообщение baron_P »

Спасибо.
1. Тут задача обратная. Я не хочу что-то получить с помощью этой программы, хочу понять как оно работает. Так что инвертирующее действие этого выражения в программе - мое предположение. Вообще, там реализован генератор псевдослучайных чисел со сдвиговым регистром и несколькими отводами, но как конкретно он работает уж хз. Попробую заменить на другой способ инверсии. Если будет работать, значить автор то и имел в виду. Радует, что такое выражение нестандартно для С - попытка поменять знак беззнаковому числу мне логичной не казалась сразу)
2. Это описание я читал, но надеялся на что-то более равернутое. Я это понял так.
В аргументе стоит число, обозначающее количество итераций 16ти битного счетчика (при значении 0 - максимальная задержка, при 65536 минимальная, т.е. ее нет). При 1 МГц цпу и 65536 итерациях, задержка будет 262,1 мс. Смущают какие-то не слишком привязанные к двоичным порядкам числа (кроме 65536), потому и хотел уточнить.
We do what we must because we can (c) GLaDOS
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

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

Сообщение Goldsmith »

baron_P писал(а):При 1 МГц цпу и 65536 итерациях, задержка будет 262,1 мс. Смущают какие-то не слишком привязанные к двоичным порядкам числа (кроме 65536), потому и хотел уточнить.
Арифметика тут простая:
The loop executes four CPU cycles per iteration
4 цикла * 65536 итераций дают те самые 262144, что при длительности цикла 1 мкс равно 262 с копейками миллисекундам.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Аватара пользователя
baron_P
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Вт сен 14, 2010 23:07:10
Откуда: Ростов

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

Сообщение baron_P »

Спасибо.
Десяток раз перечитал, а four'а и не приметил) Пока доступа к программатору нет, в понедельник посмотрю, как оно инвертироваться будет. Но появился еще вопрос.

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

-(lfsr & 1u) & 0xd0000001u

Левая часть в итоге будет типа unsigned long. Справа, исходно, unsigned char, которое, перед проведением операции "И", превращается в unsigned long. Т.е. 0xd0000001u превратится в 31 ноль и единицу в младшем разряде. И раницы между таким 0xd0000001u (7 бит) и таким 0xd00000001u (8 бит) значением в данном случае, как я думаю, нет. Но самом деле есть, с 8-ми битным числом программа черти что начинает на выхода давать. Где в моей логике ошибка?


PS: Программы собираю gcc-avr из консоли в линуксе.
We do what we must because we can (c) GLaDOS
Ответить

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