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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

WiseLord писал(а):Но &a[1] будет равно a + 4, а не a + 1, (на тех архитектурах, где int четырёхбайтовый).
не совсем так. указатель а нельзя рассматривать, как простое число, при выполнении сложения. поэтому во всех архитектурах а+4 всегда будет равно &a[4], причем не зависимо от того, какой именно размер у элемента массива. вообще эти записи эквивалентны.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

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

Сообщение WiseLord »

Виноват, был неправ:

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

#include <stdio.h>

int main(void)
{
    int x;
    int *a;
    a = &x;
    printf("0x%08d\n", a);
    printf("0x%08d\n", &a[0]);
    printf("0x%08d\n", a + 1);
    printf("0x%08d\n", &a[1]);
    return 0;
}

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

0x1084621492
0x1084621492
0x1084621496
0x1084621496
Контактная информация:
Реклама
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

ARV писал(а):во всех архитектурах а+4 всегда будет равно &a[4], причем не зависимо от того, какой именно размер у элемента массива.
Я правильно понял? Если есть uint16_t* a = 0; то после операции a += 1; (равно и a++;) в итоге a станет равно 2-м ?
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

shads писал(а): Если есть uint16_t* a = 0; то после операции a += 1; (равно и a++;) в итоге a станет равно 2-м ?
да, численное значение указателя при выполнении операций сложения/вычитания изменяется на величину, равную размеру типа. для uint16_t* a++ будет увеличивать на 2, для uint32_t* на 4 и т.д.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Вот блин...
А я думал что это касается только смещения в массивах... (например a=b[c+1])
И думал, что с указателями арифметика буквальная... т.е. сколько прибавил - на столько и увеличился..... теперь буду знать...

PS Хорошо что у меня наверное всегда массивы были однобайтные :)... поэтому проблем не замечал....
Реклама
Опытный кот
Аватара пользователя
Сообщения: 848
Зарегистрирован: Ср мар 02, 2011 07:47:39
Откуда: Уфа

Сообщение Psych »

Имя массива и есть указатель.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Сообщение FreshMan »

можно ли тело макроса разбивать на несколько строк ?
если да то как ?
#define Input_Decoder(x) {PORTB = (PORTB & 0xF6) | ((x)&1) | (((x)&2)<<2); PORTC = (PORTC & 0xFD) | (((x)&4)>>1); PORTD = (PORTD & 0xFD) | (((x)&8)>>2);}
Tell Me The Truth
Опытный кот
Аватара пользователя
Сообщения: 848
Зарегистрирован: Ср мар 02, 2011 07:47:39
Откуда: Уфа

Сообщение Psych »

FreshMan писал(а):можно ли тело макроса разбивать на несколько строк ?
Вроде бы обратный слэш:

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

 
#define Nenadoyvlekatsa\
             macrosami
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

FreshMan писал(а):можно ли тело макроса разбивать на несколько строк ?
В данном случае макроопределение не имеет особого смысла. Сделайте функцию.

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

void Input_Decoder(uint8_t x)
{
  PORTB = (PORTB & 0xF6) | (x&1) | ((x&2)<<2); 
  PORTC = (PORTC & 0xFD) | ((x&4)>>1); 
  PORTD = (PORTD & 0xFD) | ((x&8)>>2);
}
Друг Кота
Аватара пользователя
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Сообщение FreshMan »

a_skr писал(а):В данном случае макроопределение не имеет особого смысла.
ПОЧЕМУ ?
Tell Me The Truth
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение pokk »

Есть у меня switch case состоящая из 10 case и таких конструкций несколько
метки делал через #define но уже и в них начинаю путаться
вспомнил что я встречал enum но до сих пор он мне был ненужен.

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

enum case2 {
EXIT,
START,
START_1,
START_2,
.....
};


Так вот если сделать все метки через него это будет эквивалентно define ?
Скорость работы программы не изменится?
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

Мой уютный бложик... заходите!
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

Есть у меня switch case состоящая из 10 case и таких конструкций несколько
Не проще ли пересмотреть структуру программы - массив или индексный переход?
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Ещё, ЕМНИП, при замене #define на enum компилятор в случае перебора по case ругнётся в случае, если не все варианты перебраны (при отсутствии default, конечно). Тоже какой-никакой контроль.
Контактная информация:
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

WiseLord писал(а):Ещё, ЕМНИП, при замене #define на enum компилятор в случае перебора по case ругнётся в случае, если не все варианты перебраны
только при условии, что тип переменной в switch соответствует enum
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение pokk »

Не проще ли пересмотреть структуру программы - массив или индексный переход?
А можно по подробнее ?

Это я делаю протокол I2C Без delay_us

при переходе с одного case на другое выполнится автоматически задержка.
пока сделал до ASK
примерно это выглядит так.
Спойлер

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

interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
      switch(t1){
            case EXIT:{break;} //  Передачик выключен       
//------------START--------------------      
            case START:{
                SDA_1
                SCL_1
                t1=START_1;                  
                break;
            }
            case START_1:{
                SDA_0
                t1=START_1; 
                break;
            }
            case START_2:{
                SCL_0
                t1=SEND; 
                break;
            }                           
//------------Send--------------------
            case SEND:{
            //---------- даные  data
                flag_I2C=data&0x80;
                data=data<<1;
            //---------- данные пуст ?    
                if(data==0){
                    t1=ASK;           
                }
                else{
                    t1=SEND_1;
                }
            //-----------выставляем bit0 на линию------                
                if(flag_I2C==0x80){
                    SDA_1  
                }
                else{
                    SDA_0
                }
                break;
            }
            case SEND_1:{
                SCL_1
                t1=SEND_2; 
                break;
            }
            case SEND_2:{
                SCL_0
                t1=SEND;          //  циклически передаём данные
               break;
            }
//------------ASK--------------------            
            case ASK:{
                ////////////////////////////////////SDA=IN
                t1=ASK_1; 
                break;
            }
            case ASK_1:{
                SCL_1
                if(SDA==0){
                    t1=ASK_2; // идём дальше
                }
                else{
                    //ошибка
                }
                break;
            }
            case ASK_2:{
                SCL_0
                t1=ASK_3; 
                break;
            }
            case ASK_3:{
                if(SDA==1){
                    //t1=ASK_2 // идём дальше   добавить суловия куда идти
                    //SDA=out
                }
                else{
                    //ошибка
                }
                break;
            }
//------------STOP--------------------                                                                                       
            case STOP:{
                SDA_0
                SCL_1
                t1=STOP_1;                  
                break;
            }
            case STOP_1:{
                SDA_1
                t1=EXIT;                  
                break;
            }
      }
TCNT2=DELAYX;
TCNT2=0xFA;
}

Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

pokk писал(а):А можно по подробнее ?
Там вариантов много. Например можно использовать массив указателей на функции, если параметры в CASE у вас идут по порядку. Либо алгоритмы работы со списками, и прочее.
Конкретно как сейчас вам лучше организовать - не готов ответить.
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

pokk, у вас на метку START_2 код никогда не попадет) поправьте обработчик START_1.
а так все ок.
я бы писал так:

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

typedef enum{
	START = 0,
	START_1,
	START_2,
	START_3,
	....
} mode_t;
mode_t Mode;

interrupt [TIM2_OVF] void timer2_ovf_isr(void) { 
  TCNT2=DELAYX;  // это в самом начале обработчика, чтобы задержка не зависела от времени выполнения switch-case
  
  switch(Mode){
	case START:
	 ....
	 break;
	 
	case START_1:
	 ....
	 break;
	
	default:
	 ....
	 break;
  }
}
Ставим плюсы: )
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение pokk »

ibiza11 писал(а):TCNT2=DELAYX; // это в самом начале обработчика, чтобы задержка не зависела от времени выполнения switch-case
что-то не понял как задержка зависит swith-case? задал частоту 100 Khz и всё главное что бы в прерывание успело выполнится за данный период.
а где задавать частоту какая разница в любом же случает он выполнит всё прерывание.
Я вообще специально вниз поставил что бы можно было изменить задержку.
типа так:

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

interrupt [TIM2_OVF] void timer2_ovf_isr(void) {

 
  switch(Mode){
   case START:
   DELAYX=5 мк
    ....
    break;
   
   case START_1:
    ....
    break;

   case STOP:
   DELAYX=255 мк
    break;

  
   default:
    ....
    break;
  }

  TCNT2=DELAYX; 
}
WiseLord писал(а):Ещё, ЕМНИП, при замене #define на enum компилятор в случае перебора по case ругнётся в случае, если не все варианты перебраны (при отсутствии default, конечно). Тоже какой-никакой контроль.
сделал как предложил ibiza11 пару case закомментировал и нечего от CodeVision не увидел.
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

pokk писал(а):что-то не понял как задержка зависит swith-case?
прерывание таймера происходит по его переполнению. т.е. значение TCNT2 в этот момент = 0.
После входа в прерывание, таймер не останавливается, и, в зависимости от предделителя таймера, может насчитать еще несколько импульсов во время выполнения обработчика прерывания.
Операция TCNT2=DELAYX; предназначена для того, чтобы сместить начальное значение TCNT2 относительно нуля, тем самым определяя кол-во тиков таймера до момента его прерывания.
Для примера: TCNT2 = 100 - определит задержку равную (256-100)=156 тикам таймера при условии, что в начальный момент значение таймера = 0, поскольку таймер (в данном случае таймер №2) переполнится после значения 255.
Но, поскольку эта операция может быть произведена в момент, когда значение TCNT2 не равно нулю, может появиться погрешность в бОльшую сторону равная значению TCNT2 в момент совершения операции присвоения. Поэтому, чем раньше вы ее произведете, тем меньше вероятность того, что возникнет погрешность.
У любой инструкции есть время выполнения, а поскольку switch-case также является инструкцией контроллера, то и у нее есть время выполнения. Следовательно пока выполняется switch-case значение таймера может стать отличным от нуля.
Все это можно проверить в симуляторе или попытаться рассчитать, имея значение предделителя таймера.
Ставим плюсы: )
Ответить

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