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

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> Использование static переменных
rezident
сообщение Oct 8 2010, 13:54
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Сергей Борщ @ Oct 8 2010, 19:46) *
Да и хрен на нее, хоть и static. На то и оптимизатор. Пользы от переменной никакой, накой ее держать?
Не его (компилятора) собачье дело! smile.gif Пускай warning выдаст, а я уж сам решу нужна мне там переменная или не нужна. Насчет выбрасывания неиспользуемых функций - согласен, а вот насчет выбрасывания переменных типа static ...ммм... можно привести реальные примеры такого поведения с указанием конкретных компиляторов и параметров оптимизации?
Go to the top of the page
 
+Quote Post
Petka
сообщение Oct 8 2010, 14:10
Сообщение #17


Профессионал
*****

Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886



Цитата(rezident @ Oct 8 2010, 17:54) *
Не его (компилятора) собачье дело! smile.gif Пускай warning выдаст, а я уж сам решу нужна мне там переменная или не нужна. Насчет выбрасывания неиспользуемых функций - согласен, а вот насчет выбрасывания переменных типа static ...ммм... можно привести реальные примеры такого поведения с указанием конкретных компиляторов и параметров оптимизации?


Код
static int foo;

int main (void){
  return 0;
}


На любом ненулевом уровне оптимизации gcc выкидывает foo
Go to the top of the page
 
+Quote Post
Oldring
сообщение Oct 8 2010, 14:51
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(rezident @ Oct 8 2010, 17:54) *
Не его (компилятора) собачье дело! smile.gif


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

Цитата(Petka @ Oct 8 2010, 18:10) *
На любом ненулевом уровне оптимизации gcc выкидывает foo


Скорее всего выкидывает линкер, как объект, на который нет ни одной ссылки из программы.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 8 2010, 15:01
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Petka @ Oct 8 2010, 20:10) *
На любом ненулевом уровне оптимизации gcc выкидывает foo

Хм. IAR тоже выбрасывает. cranky.gif
А вот так уже нет. Но warning формирует в обоих случаях.
Код
static int foo;

int main (void)
{
  foo = 1;
  return 0;
}


Цитата(Oldring @ Oct 8 2010, 20:51) *
Скорее всего выкидывает линкер, как объект, на который нет ни одной ссылки из программы.
Нет, именно компилятор. Эта строка с объявлением переменной уже в asm-файле просто закоментарена компилятором.
Go to the top of the page
 
+Quote Post
MALLOY2
сообщение Oct 8 2010, 15:21
Сообщение #20


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



Не зряж в IAR введен Extended keyword __root с помощю его никто никогда никого не выкинет.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Oct 8 2010, 23:03
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(777777 @ Oct 8 2010, 12:46) *
Понравилос smile.gif
По таким постам легко отличать верующих от атеистов. Для верующих сила авторитета сильнее стандарта Си. smile.gif

Вера здесь не при чём. Просто я, в отличее от Сергея, работаю только в компиляторе IAR. В связи с этим не берусь обобщать. Кроме того, Сергей не раз достаточно аргументировано отвечал приводя выдержки из стандарта.

Все остальные аргументы здесь уже привели. Они совпадают с моим подходом.

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

Go to the top of the page
 
+Quote Post
aesok
сообщение Oct 9 2010, 22:02
Сообщение #22


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Код
#include <avr/io.h>
#include <avr/interrupt.h>

extern void foo (void);
volatile int volatile * p_a;

int main()
{
  foo ();
  foo ();

  return 0;
}

void foo (void)
{
  static int a = 1;

  p_a = &a;

  a = 2;

  cli ();

  // предположим что в этот момент управление
  // передаеться обработчику прерывания и в нем
  // происходит чтение локальной переменной 'a'
  // через указарель 'p_a'.

  sei ();
  
  a = 3;
  return;
}


Вопрос: Какое значение получает обработчик прерывания через указарель 'p_a', если код скомпилирован с -Os? Кто считает что 2?


Код
.global    foo
    .type    foo, @function
foo:
    ldi r24,lo8(a.1233)
    ldi r25,hi8(a.1233)
    sts p_a+1,r25
    sts p_a,r24
/* #APP */
;  23 "main.c" 1
    cli
;  0 "" 2
;  30 "main.c" 1
    sei
;  0 "" 2
/* #NOAPP */
    ldi r24,lo8(3)
    ldi r25,hi8(3)
    sts a.1233+1,r25
    sts a.1233,r24
    ret
    .size    foo, .-foo
.global    main
    .type    main, @function
main:
    rcall foo
    rcall foo
    ldi r24,lo8(0)
    ldi r25,hi8(0)
    ret
    .size    main, .-main
    .comm p_a,2,1
    .data
    .type    a.1233, @object
    .size    a.1233, 2
a.1233:
    .word    1


Правильный ответ: при первом вызове foo () 1, при последующих 3.

Анатолий.

Сообщение отредактировал aesok - Oct 9 2010, 22:02
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Oct 9 2010, 22:17
Сообщение #23


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Чтобы прерывания правильно обрабатывали глобальные переменные, меняющиеся вне прерывания, эти переменные должны быть волатильными. Есть такое правило.
Формально, p_a является волатильной и даже указывает (должна) на волатильную переменную, но в реале указывает на неволатильную. При присваивании p_a = &a должен был появиться варнинг. А в остальном, компилятор работая с "а" всё делает верно. Если бы между cli/sti был вызов функции, то перед вызовом в "а" была бы записана двойка.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
aesok
сообщение Oct 9 2010, 22:32
Сообщение #24


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(GetSmart @ Oct 10 2010, 02:17) *
Чтобы прерывания правильно обрабатывали глобальные переменные, меняющиеся вне прерывания, эти переменные должны быть волатильными. Есть такое правило.

Это я и пытаюсь показать на примере 777777

Цитата
Формально, p_a является волатильной и даже указывает (должна) на волатильную переменную, но в реале указывает на неволатильную. При присваивании p_a = &a должен был появиться варнинг.


Никаких варингов нет.

Цитата
А в остальном, компилятор работая с "а" всё делает верно. Если бы между cli/sti был вызов функции, то перед вызовом в "а" была бы записана двойка.


Да, с небольшим уточнением, если эта дополнительная функция проинлайнилась в foo () и указатель p_a в ней не используеться, то записи двойки в 'a' не будет.

Анатолий.
Go to the top of the page
 
+Quote Post
777777
сообщение Oct 10 2010, 08:57
Сообщение #25


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(aesok @ Oct 10 2010, 02:02) *
Правильный ответ: при первом вызове foo () 1, при последующих 3.

Разумеется, потому что с точки зрения компилятора у тебя идут две подряд строки
a = 2;
a = 3;
Результат выполнения этой программы - занесения 3 в переменную a. Но это последнее присваивание компилятор не имеет права выбрасывать потому что a - static! И этот результат может понадобиться при последующих вызовах этой функции.

В моем случае последовательность была такая:
Код
    uint8_t cmd[3] = { 8, mn, 0 };

    pTWI = cmd;
    SendSLA();

Здесь компилятор не имеет права выбрасывать ничего, даже если бы pTWI было не volatile потому что:
а) адрес cmd присваивается глобальной переменной, сделовательно cmd используется и он должен быть инициализирован;
б) pTWI - глобальная переменная, следовательно она может использоваться в других функциях, а значит по выходу из функции в ней должен быть адрес cmd;
в) более того, следом вызывается некая глобальная функция, поэтому компилятор обязан предположить, что pTWI может использоваться в этой функции, следовательно адрес cmd должен быть присвое ей до вызова SendSLA
После того как я сделал массив static ограничений стало еще больше.
Go to the top of the page
 
+Quote Post
777777
сообщение Oct 10 2010, 10:03
Сообщение #26


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(GetSmart @ Oct 10 2010, 02:17) *
Чтобы прерывания правильно обрабатывали глобальные переменные, меняющиеся вне прерывания, эти переменные должны быть волатильными. Есть такое правило.

Обалденное определение, мне нравится. А что значит "правильно обрабатывали"? А как можно обрабатывать неправильно?
Вообще-то у него есть строго определенное значение: оно заставляет компилятор предполагать, что значение этой переменной может меняться само по себе, помимо хода выполнения программы:
Цитата
An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2.3. Furthermore, at every sequence point the value last stored in the object shall agree with that prescribed by the abstract machine, except as modified by the unknown factors mentioned previously. What constitutes an access to an object that has volatile-qualified type is implementation-defined.

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


Цитата(GetSmart @ Oct 10 2010, 02:17) *
Если бы между cli/sti был вызов функции, то перед вызовом в "а" была бы записана двойка.

Вообще говоря да, компилятор обязан предположить, что 'a' может потребоваться в той функции, но в данном случае она static и поэтому из той функции недоступна.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Oct 10 2010, 12:07
Сообщение #27


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(777777 @ Oct 10 2010, 14:03) *
компилятор обязан предположить

Вот мы все на языке лирики, а меж тем - чистая теория графов smile.gif удалил вершину - и нет проблемы переменной
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Oct 10 2010, 12:31
Сообщение #28


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(777777 @ Oct 10 2010, 12:57) *
Разумеется...
...последнее присваивание компилятор не имеет права выбрасывать потому что a - static!
Вы не правы. Привязались к статику уак банный лист:-)
Он не для этого задуман. И все ваши домыслы можно поставить с ног на голову путём изменения опций компилятора и линкера.
Остыньте и сделайте два-три глубоких вдоха. В этом споре вы уже проиграли. Сэ ля виsad.gif

PS
aesok, с возвращением!


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
777777
сообщение Oct 11 2010, 04:30
Сообщение #29


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(demiurg_spb @ Oct 10 2010, 16:31) *
Вы не правы. Привязались к статику уак банный лист:-)
Он не для этого задуман. И все ваши домыслы можно поставить с ног на голову путём изменения опций компилятора и линкера.
Остыньте и сделайте два-три глубоких вдоха. В этом споре вы уже проиграли.

А для чего же он создан? Приведите раздел стандарта который это объясняет. В крайнем случае, приведите пример программы с набором опций компилятора и линкера. Вы ничего этого не сделали, но почему-то объявляете, что я проиграл.

Статик создан именно для того, чтобы его значение, установленное в функции, сохранялось при выходе из нее и было таким же при повторном входе в эту функцию. Компилятор имеет большую свободу действий, но такое поведение переменной он обязан обеспечивать. Если у вас есть другие мнения на этот счет - объясните, желательно с убедительной аргументацией.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Oct 11 2010, 04:41
Сообщение #30


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(777777 @ Oct 11 2010, 09:30) *
Статик создан именно для того, чтобы его значение, установленное в функции, сохранялось при выходе из нее и было таким же при повторном входе в эту функцию.

Это такая же голимая интерпретация как и я писал об volatille smile.gif
Я хотя бы для себя ввёл то правило, являющееся следствием оптимизации компиляторов. То есть "моё" правило, напрямую не касалось определения volatille, а просто юзало его.

Статик просто размещает переменную в каком-то там сегменте (bss или др.). И всё. Остальное на совести компилятора.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 12:21
Рейтинг@Mail.ru


Страница сгенерированна за 0.01491 секунд с 7
ELECTRONIX ©2004-2016