Перейти к содержанию
    

Переопределение переменной в теле функции.

Впервые встретил вот такое

void ILI9341_Init() 
{
    ILI9341_WriteCommand(0xCB);
    {
        uint8_t data[] = { 0x39, 0x2C, 0x00, 0x34, 0x02 };
        ILI9341_WriteData(data, sizeof(data));
    }
  
    ILI9341_WriteCommand(0xCF);
    {
       uint8_t data[] = { 0x00, 0xC1, 0x30 };
       ILI9341_WriteData(data, sizeof(data));
    }
  
    //и так далее
  
  }

стоит пользоваться такой конструкцией? мне она не нравиться честно говоря.

интересно как компайлер поведет себя? выделит отдельный массив на стаке при каждом определении?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, jenya7 said:

интересно как компайлер поведет себя?

Это стандартный приём. Иногда именно так и надо делать.

1 hour ago, jenya7 said:

выделит отдельный массив на стаке при каждом определении?

В каждом блоке кода, обрамлённом фигурными скобками, происходит создание и инициализация объектов. При выходе из такого блока происходит их разрушение. Другими словами, при входе в блок вы можете быть уверены, что имено сейчас, на входе, у вас будут свежеинициализированные переменные. При выходе - они больше никогда не появятся, их как будто бы и не существовало. В случае входа в блок с использованием Си++ у вас будут вызваны конструкторы объектов, а на выходе - деструкторы. Как это всё оформит компилятор - его личное дело. Главное - соблюсти стандарт, если получится)))))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

54 минуты назад, jenya7 сказал:

стоит пользоваться такой конструкцией? мне она не нравиться честно говоря.

С вероятностью 99.9% - типичный говнокод. Не стоит.

54 минуты назад, jenya7 сказал:

интересно как компайлер поведет себя? выделит отдельный массив на стаке при каждом определении?

На усмотрение компилятора.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

25 minutes ago, haker_fox said:

Это стандартный приём. Иногда именно так и надо делать.

В каждом блоке кода, обрамлённом фигурными скобками, происходит создание и инициализация объектов. При выходе из такого блока происходит их разрушение. Другими словами, при входе в блок вы можете быть уверены, что имено сейчас, на входе, у вас будут свежеинициализированные переменные. При выходе - они больше никогда не появятся, их как будто бы и не существовало.

выход из блока это не выход из функции. надо полагать переменные остануться на стаке.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

21 минуту назад, haker_fox сказал:

В каждом блоке кода, обрамлённом фигурными скобками, происходит создание и инициализация объектов...

Зависит много от чего (соглашение о вызовах, компилятор, платформа и т.д.).
Посмотрите, например, в любой сгенерированный листинг функции для Cortex-Mx.
Вы же, вроде как, под них пишете, в IAR. Резерв стека происходит один раз в начале функции.
Освобождение - также, один раз, только в конце. Это касается всех локальных переменных функции.

Касательно ТС: я бы не стал так писать... ИМХО, реально все отдается на откуп компилятора.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 minutes ago, jcxz said:

С вероятностью 99.9% - типичный говнокод. Не стоит.

На усмотрение компилятора.

вот как чувствовал :))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 minutes ago, Arlleex said:

Зависит много от чего (соглашение о вызовах, компилятор, платформа и т.д.).

Я не на уровне машинных команд имею в виду, а на уровне стандарта языка) То, что машинный код может быть каким угодно, это понятно)

3 minutes ago, jenya7 said:

вот как чувствовал :))

Не чувствовать надо, хотя и не без этого, а понимать) Например, я часто использую такой код с scmRTOS

void foo() {
  // some code here
  {
    OS::TCritSec cs; // здесь создаётся объект, в конструкторе которого сохраняется текущее слово состояния процессора и запрещаются глобально прерывания
    // здесь выполняем код, требующий критической секции
    
    // а вот выходить из критической секции не нужно, деструктор это сделает сам
  }
  // some code here, и здесь атомарное выполнение кода не требуется
}

 

6 minutes ago, Arlleex said:

Резерв стека происходит один раз в начале функции

Это и наблюдаю, но не полагаюсь на такое поведение компилятора. Я прекрасно понимаю, что он волен делать, как считает нужным)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

15 минут назад, jcxz сказал:

С вероятностью 99.9% - типичный говнокод. Не стоит.

То что конструкция выглядит не слишком красиво, ни о чем не говорит. С точки зрения стандарта и логики все абсолютно корректно. Можно подумать, что если массивы назвать data1 и data2, то что-то измениться. Ничего не измениться :dirol:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

22 минуты назад, jcxz сказал:

С вероятностью 99.9% - типичный говнокод. Не стоит.

Можно аргументы?

13 минут назад, jenya7 сказал:

выход из блока это не выход из функции. надо полагать переменные остануться на стаке.

Ясное дело, что ячейки памяти из стека никто напильником выпиливать не будет, ячейки останутся на своем месте и данные в них тоже. Но обратиться к ним по имени переменной вы не сможете - потому что за пределами блока это имя (эта переменная) не существует. А просто обратиться к данным на стеке можно сотней разных способов и  это никак не пересекается с объявлением локальных переменных внутри блока.

12 минут назад, jenya7 сказал:

вот как чувствовал :))

Он или не понял вопроса, или ерунду сказал сознательно. А вы радуетесь.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 минуты назад, Baser сказал:

То что конструкция выглядит не слишком красиво, ни о чем не говорит...

С точки зрения Си - все ок.
А вот с точки зрения реального железа возможен бесполезный перерасход памяти.
И увеличение количества инструкций для смены указателей в регистрах... ИМХО.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, Сергей Борщ сказал:

Можно аргументы?

Куча лишних операций (выделение памяти на стеке, копирование массива в эту память из const-памяти) там где это скорей всего (99.9%) не нужно - это Вам не "аргументы"?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 minutes ago, Baser said:

То что конструкция выглядит не слишком красиво, ни о чем не говорит. С точки зрения стандарта и логики все абсолютно корректно. Можно подумать, что если массивы назвать data1 и data2, то что-то измениться. Ничего не измениться :dirol:

назвать data и пользоваться только им не загружая стек

ILI9341_WriteCommand(0xCB);
data[0] = 0x39;     
data[1] = 0x2C;
data[2] = 0x00;
data[3] = 0x34;
data[4] = 0x02
ILI9341_WriteData(data, 5);

ILI9341_WriteCommand(0xCF);
data[0] = 0x00;
data[1] = 0xC1;
data[2] = 0x30;
ILI9341_WriteData(data, 3);

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 минут назад, Baser сказал:

То что конструкция выглядит не слишком красиво, ни о чем не говорит. С точки зрения стандарта и логики все абсолютно корректно.

С точки зрения языка, конструкция:

int x = atoi("1234");

вместо:

int x = 1234;

тоже вполне корректна. А по факту 1-е - говнокод.  :unknw:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, Arlleex сказал:

Возможен бесполезный перерасход памяти.

Давайте тогда конкретные примеры, как это может произойти. Я во всех вменяемых компиляторах наблюдаю резервирование на стеке необходимого объема после входа в функцию и освобождение перед выходом. Не пересекающиеся во времени данные занимают одну и ту же память.

1 минуту назад, jcxz сказал:

Куча лишних операций (выделение памяти на стеке, копирование массива в эту память из const-памяти) там где это скорей всего (99.9%) не нужно - это Вам не "аргументы"?

Так это придирки. Может там архитектура такая (типа AVR), которая не умеет по uint8_t * из флеша доставать. Вопрос-то не об этом был, а о переменных с одинаковыми именами внутри разных блоков.

2 минуты назад, jenya7 сказал:

назвать data и пользоваться только им не загружая стек

И где этот data будет располагаться?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 minutes ago, Сергей Борщ said:

И где этот data будет располагаться?

 

но это будет один локальный массив.

void ILI9341_Init() 
{
    uint8_t data[16];
    
    ILI9341_WriteCommand(0xCB);
    data[0] = 0x39;     
    data[1] = 0x2C;
    data[2] = 0x00;
    data[3] = 0x34;
    data[4] = 0x02;
    ILI9341_WriteData(data, 5);

    ILI9341_WriteCommand(0xCF);
    data[0] = 0x00;
    data[1] = 0xC1;
    data[2] = 0x30;
    ILI9341_WriteData(data, 3);
  }

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...