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

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

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

Сообщение FreshMan »

под переменную выделяется минимум 1 Байт
а сколько выделяется памяти под указатель на оную переменную ?
Tell Me The Truth
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

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

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

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

Сообщение FreshMan »

для 8 битных AVR
Tell Me The Truth
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

FreshMan писал(а):для 8 битных AVR

размер указателя обычно совпадает с размером int для платформы. собственно, с адресным пространством памяти размер int и [должен быть]связан... но, естественно, полно исключений.

WinAVR (avr-gcc) придерживается мнения, что указатель имеет размер 16 бит, причем даже указатель на flash, хотя объем flash у AVR встречается и поболее 64К.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
FreshMan
Друг Кота
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

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

Сообщение FreshMan »

имеется два массива

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

unsigned char BrightnessOldDigits[6]={10,10,10,10,10,10};
unsigned char BrightnessNewDigits[6]={10,10,10,10,10,10};

и указатель

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

uint8_t *p_brightness[12] = {&BrightnessOldDigits[2],  // когда var=0
                           &BrightnessOldDigits[3],  // когда var=1
                           &BrightnessOldDigits[4],  // когда var=2
                           &BrightnessOldDigits[5],  // когда var=3
                           &BrightnessNewDigits[0],  // когда var=4
                           &BrightnessNewDigits[1],  // когда var=5
                           &BrightnessNewDigits[2],  // когда var=6
                           &BrightnessNewDigits[3],  // когда var=7
                           &BrightnessNewDigits[4],  // когда var=8
                           &BrightnessNewDigits[5],  // когда var=9
                           &BrightnessOldDigits[0],  // когда var=10
                           &BrightnessOldDigits[1]}; // когда var=11

размер оного указателя равен 1 байт ?
Tell Me The Truth
uk8amk
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

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

Сообщение uk8amk »

uint8_t *p_brightness
uint16_t *p_brightness
uint32_t *p_brightness

для AVR будут все по 16 бит.
А вот при разыменовании происходит доступ к 8, 16 или 32 битам соответственно.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

FreshMan писал(а):имеется два массива и указатель

на самом деле у вас МАССИВ УКАЗАТЕЛЕЙ
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
FreshMan
Друг Кота
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

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

Сообщение FreshMan »

а допускается ли такое безобразие

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

uint8_t p_brightness[12]={BrightnessOldDigits[2],  // êîãäà var=0
                           BrightnessOldDigits[3],  // êîãäà var=1
                           BrightnessOldDigits[4],  // êîãäà var=2
                           BrightnessOldDigits[5],  // êîãäà var=3
                           BrightnessNewDigits[0],  // êîãäà var=4
                           BrightnessNewDigits[1],  // êîãäà var=5
                           BrightnessNewDigits[2],  // êîãäà var=6
                           BrightnessNewDigits[3],  // êîãäà var=7
                           BrightnessNewDigits[4],  // êîãäà var=8
                           BrightnessNewDigits[5],  // êîãäà var=9
                           BrightnessOldDigits[0],  // êîãäà var=10
                           BrightnessOldDigits[1]}; // êîãäà var=11


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

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

Сообщение Psych »

FreshMan писал(а):а допускается ли такое безобразие

Че эт безобразие-то?!! Вполне естественно.

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

*p_brightness=BrightnessOldDigits[2] // имя массива указатель на нуевой элемент

p_brightness[2]=BrightnessOldDigits[4]      //   Одинаково
*(p_brightness+2)=BrightnessOldDigits[4]  //

uint8_t p_brightness[]={......} // можно число не указывать если инициализируете
VLeshka
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт июл 04, 2013 15:15:22

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

Сообщение VLeshka »

Привет всем.

Создаю программу приёма пакета через uart, используя прерывание.
Код:

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

#pragma vector = USCIAB0RX_VECTOR 
__interrupt void USCIAB0RX_VECTOR_PRE (void)
{
    char buf = UCA0RXBUF; //сбрасываем прерывание
    addItem(ch_exp,buf);  //добавляем символ buf к массиву символов ch_exp
    UARTWriteString(ch_exp);
    //далее заводим таймер на 100мс
}


Конец пакета буду определять просто - по разрыву по времени между принятыми символвми более 100мс.

Проблема в процедуре addItem (написал по докам из яндекса):
Код:

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

void addItem(char *&c, char sim)
{
 char *tt; //использую свой метод определения длины строки, это наверно почти бред:)
  tt = c;
  int ii = 0;
  while (*tt)
  {
    ii++;
    tt++;
  }
  char *t = new char[ii+1]; //но даже если задавать размерность вручную, то тоже виснет
  for (int i=0; i<ii;i++)
     t[i] = c[i]; 
  t[ii] = sim;   
  delete[] c;
  c = t;
}


При первом проходе через процедуру, добавляется символ к массиву и возвращается изменённый массив нормально.
При втором проходе, помимо добавления символа добавляется ещё и символ '.'.
При третьем проходе, всё виснет.

Сперва грешил на символ \0 в конце строки, но вроде он ставится автоматом, и не надо заботиться о его добавлении.
В чём проблема?
Аватара пользователя
GARMIN
Держит паяльник хвостом
Сообщения: 952
Зарегистрирован: Вс дек 02, 2012 16:58:33
Откуда: от туда
Контактная информация:

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

Сообщение GARMIN »

VLeshka писал(а):

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

void addItem(char *&c, char sim)
{
 char *tt; // это бред
  tt = c;

В чём проблема?

Как ты приравниваешь указатель на адрес переменной к указателю на переменную?
VLeshka
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт июл 04, 2013 15:15:22

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

Сообщение VLeshka »

GARMIN писал(а):
VLeshka писал(а):

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

void addItem(char *&c, char sim)
{
 char *tt; // это бред
  tt = c;

В чём проблема?

Как ты приравниваешь указатель на адрес переменной к указателю на переменную?

Спасибо за указание на эту ошибку. Накидал код:

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

void addItem(char &c, char sim) //тут была ошибка
{
 char *tt;
  tt = &c;
  int ii = 0;
  while (*tt)
  {
    ii++;
    tt++;
  }
  char *t = new char[ii+1];
  for (int i=0; i<ii;i++)
  {
    t[i] = c; 
    c++;
  }
  t[ii] = sim;   
  c = t[0];
}


и вызываем его:

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

addItem(ch_exp[0],'a');

Вроде работает, но так же с "фокусами в конце массива". Доберусь до компа - проверю досконально (прошлой ночью времени было мало).
Аватара пользователя
GARMIN
Держит паяльник хвостом
Сообщения: 952
Зарегистрирован: Вс дек 02, 2012 16:58:33
Откуда: от туда
Контактная информация:

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

Сообщение GARMIN »

void addItem(char &c, char sim) //тут была ошибка
{}

и вызываем его:
addItem(ch_exp[0],'a');

Опять двадцать пять:
ch_exp[0] передаётся по значению.
А ты объявляешь его адресом:
char &c
VLeshka
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт июл 04, 2013 15:15:22

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

Сообщение VLeshka »

GARMIN писал(а):Опять двадцать пять:
ch_exp[0] передаётся по значению.
А ты объявляешь его адресом:
char &c

спасибо.

Я после очередного сеанса связи с MSP430 понял, что мне надо изучать поставленную мною тему с "Hello world". :)
Итак, в обработчике прерывания uart-порта при приёме, я написал простенький код по добавлению символа к строке, и выводу этой строки обратно в uart [на комп, для наглядного контроля].

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

char *ch_exp="Mod";
int cnt=3;

#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_VECTOR_PRE (void)
{
char buf = UCA0RXBUF; //сбрасываем прерывание
    P1OUT ^= (BIT0 + BIT6); //вкл и выкл диоды

    UARTWriteString(ch_exp); //выводит строку в uart; всегда нормально работает
    UARTWriteString("Ура"); //всегда нормально работает
   
    char *t = new char[cnt+1]; //здесь на второй раз зависает
    for (int i=0; i<cnt;i++)
      t[i] = ch_exp[i]; 
    t[cnt] = 'a';
    t[cnt+1] = '\0';   
    cnt++;
    ch_exp = t;
   
   
    UARTWriteString(ch_exp);
}

При первом проходе через этот код всё нормально. Но не могу понять, почему намертво зависает при втором проходе на строке:

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

char *t = new char[cnt+1];

Указатель t - локальный и не требует такого удаления:

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

//delete(t); //впрочем, вставлял - не помогает

Упёрся уже в тупой угол. В чём ошибаюсь???
Аватара пользователя
GARMIN
Держит паяльник хвостом
Сообщения: 952
Зарегистрирован: Вс дек 02, 2012 16:58:33
Откуда: от туда
Контактная информация:

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

Сообщение GARMIN »

VLeshka писал(а):При первом проходе через этот код всё нормально. Но не могу понять, почему намертво зависает при втором проходе на строке:

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

char *t = new char[cnt+1];

Указатель t - локальный и не требует такого удаления
Упёрся уже в тупой угол. В чём ошибаюсь???

Каким ерундовым софтом ты пользуешься, если он тебе компилирует этот код без ошибок?
Ну разберись с указателями и массивами наконец. Почитай, чем отличается элемент массива от указателя на этот элемент.
Тебе дважды говорил разобраться. Опять те же грабли.
Жевать не буду. Читай учебник до просветления.
VLeshka
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт июл 04, 2013 15:15:22

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

Сообщение VLeshka »

GARMIN писал(а):Каким ерундовым софтом ты пользуешься, если он тебе компилирует этот код без ошибок?

спасибо за наводку.

GARMIN писал(а):Ну разберись с указателями и массивами наконец. Почитай, чем отличается элемент массива от указателя на этот элемент.
Тебе дважды говорил разобраться. Опять те же грабли.
Жевать не буду. Читай учебник до просветления.

ок. Вопросы закончились.
Аватара пользователя
Goodefine
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср апр 16, 2008 13:22:54
Откуда: Приднестровье, Тирасполь

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

Сообщение Goodefine »

GARMIN писал(а):Каким ерундовым софтом ты пользуешься, если он тебе компилирует этот код без ошибок?

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

char *t = new char[cnt+1];

А где в этом коде ошибка? Стандартная операция выделения памяти под массив в куче с инициализацией указателя.
Жевать не буду. Читай учебник до просветления.

Гм.. категоричное заявление :))
спасибо за наводку.

Посмотрите чему равно cnt в момент выделения памяти. Вполне возможно что в этот момент переменная не инициализирована и содержит мусор, соответственно память выделиться не может. Поставьте также ловушку на исключение std::bad_alloc - скорее всего в него программа и влетает.
Указатель t - локальный и не требует такого удаления:

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

//delete(t); //впрочем, вставлял - не помогает


Не знаю диалекта вашего С++, но обычно массив правильно удаляют так

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

 delete[] t;

Т.е. надо освобождать весь массив, а не указатель - и об этом надо сообщать компилятору
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Аватара пользователя
GARMIN
Держит паяльник хвостом
Сообщения: 952
Зарегистрирован: Вс дек 02, 2012 16:58:33
Откуда: от туда
Контактная информация:

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

Сообщение GARMIN »

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

И таки да, в предыдущем посте протупил. :oops: Буду внимательнее.
VLeshka
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт июл 04, 2013 15:15:22

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

Сообщение VLeshka »

Волею случая, использую [глобальный] статический массив. Сделал инкремент массива по указателю, но всё равно это делал используя статический массив (создаю статический массив, указываю в конце символ '\0' и ставлю указатель на этот массив) - так что перешёл на статический массив, как и делается в примерах для MSP430 по всему интернету.
srg320
Встал на лапы
Сообщения: 85
Зарегистрирован: Пт фев 01, 2013 17:47:26
Откуда: Украина, Луганская область

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

Сообщение srg320 »

Вопрос по С++.

Есть класс Свойства
Спойлер

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

template<typename Type, 
        typename Owner,
        Type (Owner::*Getter)(),
        void (Owner::*Setter)(Type)>
class Property
{
protected:
    Owner * m_owner;

public:
    operator Type () const
    {
        return (m_owner->*Getter)();
    }
   
    Type get() const
    {
        return (m_owner->*Getter)();
    }
   
    void operator  =(Type data)
    {
        (m_owner->*Setter)(data);
    }
 
    Property() :
        m_owner(0)
    {}
   
    Property(Owner * const owner) :
        m_owner(owner)
    {}
};

и пример использования
Спойлер

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

class Rectangle
{
public:
    int X;
    int Y;
    int Width;
    int Height;
   
    Rectangle() :
        X(0),
        Y(0),
        Width(0),
        Height(0)
    {}
};

class Control
{
private:
    Rectangle bounds;
    int width;
   
    void setBounds(Rectangle value) { bounds = value;}
    Rectangle getBounds() { return bounds; }
    void setWidth(int value) { width = value;}
    int getWidth() { return width; }
   
public:
    Control() :
        Bounds(this),
        Width(this)
    {}
   
    Property<Rectangle, Control, &Control::getBounds, &Control::setBounds> Bounds;
    Property<int, Control, &Control::getWidth, &Control::setWidth> Width;
};

int main()
{
    int x, width;
   
    Control* c = new Control();
   
    width = c->Width;
   
    x = ((Rectangle)c->Bounds).X;    //такой вариант работает
   
    x = c->Bounds.get().X;               //и такой
   
    Rectangle bounds = c->Bounds;  //и такой
    x = bounds.X;
   
    x = c->Bounds.X;                      //!!! а такой - нет
   
    return 0;
}


Когда тип Свойства простой, то проблем нет, а когда типом Свойства является класс, то нет доступа к полям класса. Или по другому и нельзя, или я не правильно написал перегрузку оператора приведения типа в классе Property, а может есть другие варианты достичь желаемого результата. Пишу в IARе, но думаю разницы нет какой компилятор.
Хотелось бы писать так

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

x = c->Bounds.X; 
так и красивее и проще читать

а не так

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

x = ((Rectangle)c->Bounds).X;
или так

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

x = c->Bounds.get().X;

Если кто знает, подскажите.
Заранее благодарен.
Ответить

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