|
Использование static переменных |
|
|
3 страниц
< 1 2 3
|
 |
Ответов
(30 - 40)
|
Oct 11 2010, 07:36
|

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

|
Цитата(GetSmart @ Oct 11 2010, 08:41)  Статик просто размещает переменную в каком-то там сегменте (bss или др.). И всё. Остальное на совести компилятора. Что именно "всё остальное"? Стандарт четко определяет время жизни (lifetime) переменной. Что по-вашему означает этот термин? Когда компилятор выкидывает какие-либо присвоения, то он это делает в том случае, когда видит, что они не потребуются до конца жизни переменной. Если же ее время жизни - до конца программы, то как он может их выкинуть? Он обязан полагаться на то, что где-то в программе она потребуется. Или вы считаете, что он может проанализировать программу и выяснить, что функция больше вызываться не будет и отменить присваивание? Это даже программист не может сделать, для этого он и выполняет отладку. Вы даете компилятору слишком много воли. Если бы это было так, то программы было бы невозможно писать. Наслушавшись таких разговоров некоторые предпочитают асм, думая, что компилятор действительно может сгенерировать не то, что написал программист. Но к счастью это не так.
|
|
|
|
|
Oct 11 2010, 07:55
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Я уже потерял суть спора. Чё не нравится? В смысле, что компилятор (и какой?) сделал не так, как хотелось? Цитата(777777 @ Oct 11 2010, 12:36)  Что именно "всё остальное"? Стандарт четко определяет время жизни (lifetime) переменной. Что по-вашему означает этот термин? В сегменте bss эта переменная будет жить вечно. Довольны? Вопрос только в том, выкинет ли компилятор какое-нибудь присваивание в эту переменную.
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Oct 11 2010, 08:10
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(rezident @ Oct 8 2010, 17:54)  Не его (компилятора) собачье дело!  Пускай warning выдаст, а я уж сам решу нужна мне там переменная или не нужна. Насчет выбрасывания неиспользуемых функций - согласен, а вот насчет выбрасывания переменных типа static ...ммм... можно привести реальные примеры такого поведения с указанием конкретных компиляторов и параметров оптимизации? Это уж как вы ему (компилятору) укажете. Выбрасывать-не выбрасывать, предупреждать-не отвлекать на всякую ботву и тд. По крайней мере GCC так работает. ключ -fdata-sections позволяет выкидывать неиспользуемые секции данных.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Oct 11 2010, 08:58
|

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

|
Цитата(777777 @ Oct 11 2010, 08:30)  А для чего же он создан? Приведите раздел стандарта который это объясняет. В крайнем случае, приведите пример программы с набором опций компилятора и линкера. Вы ничего этого не сделали... Для себя я уже давно всё сделал, а Вам народ неоднократно писал про это: Код CFLAGS += --combine CFLAGS += -fwhole-program CFLAGS += -ffunction-sections CFLAGS += -fdata-sections С такими опциями со статической переменной может быть вообще всё что угодно (всё будет сильно зависеть от контекста Вашей программы).
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Oct 11 2010, 10:20
|

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

|
Цитата(demiurg_spb @ Oct 11 2010, 12:58)  Для себя я уже давно всё сделал, а Вам народ неоднократно писал про это: Код CFLAGS += --combine CFLAGS += -fwhole-program CFLAGS += -ffunction-sections CFLAGS += -fdata-sections С такими опциями со статической переменной может быть вообще всё что угодно Ну что ж, попробуем тупо воткнуть их в проект Код int main() { foo(); }
volatile int volatile * p_a;
void foo (void) { static int a;
p_a = &a; a = 2; a = 3; } Получаем на выходе: Код void foo (void) { static int a;
p_a = &a; 56: 80 e0 ldi r24, 0x00; 0 58: 91 e0 ldi r25, 0x01; 1 5a: 90 93 03 01 sts 0x0103, r25 5e: 80 93 02 01 sts 0x0102, r24 a = 2; a = 3; 62: 83 e0 ldi r24, 0x03; 3 64: 90 e0 ldi r25, 0x00; 0 66: 90 93 01 01 sts 0x0101, r25 6a: 80 93 00 01 sts 0x0100, r24 Если между присваиваниями воткнуть обращение к какой-нибудь функции (даже к ней самой), то он и первое присваивание не выкинет: Код void foo (void) { static int a;
p_a = &a; 7e: 80 e0 ldi r24, 0x00; 0 80: 91 e0 ldi r25, 0x01; 1 82: 90 93 03 01 sts 0x0103, r25 86: 80 93 02 01 sts 0x0102, r24 a = 2; 8a: 82 e0 ldi r24, 0x02; 2 8c: 90 e0 ldi r25, 0x00; 0 8e: 90 93 01 01 sts 0x0101, r25 92: 80 93 00 01 sts 0x0100, r24 foo(); 96: df df rcall .-66 ; 0x56 <foo> a = 3; 98: 83 e0 ldi r24, 0x03; 3 9a: 90 e0 ldi r25, 0x00; 0 9c: 90 93 01 01 sts 0x0101, r25 a0: 80 93 00 01 sts 0x0100, r24 Цитата(demiurg_spb @ Oct 11 2010, 12:58)  (всё будет сильно зависеть от контекста Вашей программы). Ну, если например в ней не будет обращений к foo, то он ее выкинет, это отследить не сложно. Но если обращение есть, то никакой самодеятельности не будет. (Если только там нет ключей, заставляющих его нарушать стандарт, но я сомневаюсь и наличии таковых)
|
|
|
|
|
Oct 11 2010, 10:52
|

Профессионал
    
Группа: Свой
Сообщений: 1 003
Регистрация: 20-01-05
Пользователь №: 2 072

|
Цитата(777777 @ Oct 11 2010, 07:30)  Статик создан именно для того, чтобы его значение, установленное в функции, сохранялось при выходе из нее и было таким же при повторном входе в эту функцию. Оригинально. Вообще ключевое слово 'static' определяет область видимости переменной, а в контексте функции к этому добавляется требование ее размещения в области данных, а не стека. Вот и все. Больше компилятор ничего не ограничивает, и если он достаточно умный, то найдя только присваивания данной переменной без передачи (или возврата) ее адреса в другие функции имеет полное право оптимизировать использование этой переменной, вплоть до полного исключения ее из результата компиляции.
|
|
|
|
|
Oct 11 2010, 11:10
|

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

|
Цитата(halfdoom @ Oct 11 2010, 14:52)  Оригинально. Вообще ключевое слово 'static' определяет область видимости переменной, а в контексте функции к этому добавляется требование ее размещения в области данных, а не стека. Вот и все. Больше компилятор ничего не ограничивает, и если он достаточно умный, то найдя только присваивания данной переменной без передачи (или возврата) ее адреса в другие функции имеет полное право оптимизировать использование этой переменной, вплоть до полного исключения ее из результата компиляции. Ключевое слово - lifetime. У static переменной оно бесконечное. Поэтому наличие только присваивания не может служить основанием для того чтобы заявлять о ее неиспользовании. Она может понадобиться при следующем вызове функции. И вообще, если компилятор выкидывает какую-то переменную или часть кода, то это означает что и без оптимизаций эта переменная/код не будет использована. Поэтому не стоит так бояться "самодеятельности" компилятора, если таковая обнаружится, не спешите выключать оптимизацию, лучше повнимательнее посмотрите исходник. Цитата(GetSmart @ Oct 11 2010, 14:58)  ...переменной <==> функции... С самого начала речь шла о static переменных в контексте функций.
|
|
|
|
|
Oct 11 2010, 11:18
|

Профессионал
    
Группа: Свой
Сообщений: 1 003
Регистрация: 20-01-05
Пользователь №: 2 072

|
Цитата(777777 @ Oct 11 2010, 14:10)  Ключевое слово - lifetime. У static переменной оно бесконечное. Поэтому наличие только присваивания не может служить основанием для того чтобы заявлять о ее неиспользовании. Она может понадобиться при следующем вызове функции. Современные методы анализа потока данных и кода позволяют выяснить, что в конструкциях типа приведенной ниже, ни при первом, ни при последующем вызовах необходимости в выделении места под переменную нет. Код int test(int aa) { static int bb = 5;
bb = 3; bb = 2; return aa * bb; /* это будет заменено на aa * 2, с последующим удалением bb */ } В случае с исходником из поста 35, компилятор все делает правильно, т.к. имеется использование адреса переменной вне функции.
|
|
|
|
|
Oct 11 2010, 11:25
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(777777 @ Oct 11 2010, 16:10)  ... Поэтому наличие только присваивания не может служить основанием для того чтобы заявлять о ее неиспользовании. Она может понадобиться при следующем вызове функции. Отсутствие её чтения - может. Этот факт анализируют (почти) все современные компиляторы. Могут выдавать ремарку или варнинг. Особенно на "статик" (не глобальную/межмодульную). Шипко умные могут даже выкинуть её, если она не волатильная. Цитата(777777 @ Oct 11 2010, 15:20)  Ну, если например в ней не будет обращений к foo, то он ее выкинет, это отследить не сложно. Но если обращение есть, то никакой самодеятельности не будет. Следите за ходом мысли. Если foo() сделать статиком, то она рискует быть удалённой, если внутри модуля она на вызывается и адрес её не используется. Даже на 99% она будет удалена современными компиляторами. То же самое относится и к статик переменным. Если внутри функции (аналог модуля для статик функции) переменная не читается, то не важно есть ли в неё запись, она может быть удалена. Если её адрес используется/записывается в другую переменную, то идёт рекурсия по анализу использования этой второй переменной. Если она не читается, а только прописывается, то сперва удаляется эта вторая переменная, а потом удаляется первая переменная, которая "статик". Всё по-чесноку.
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Oct 11 2010, 12:49
|

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

|
Цитата(777777 @ Oct 11 2010, 14:20)  Ну, если например в ней не будет обращений к foo, то он ее выкинет, это отследить не сложно. Но если обращение есть, то никакой самодеятельности не будет. (Если только там нет ключей, заставляющих его нарушать стандарт, но я сомневаюсь и наличии таковых) Как уже говорили, при использовании ключей combine и fwhole-program, все функции становятся static. И в этом случае у компилятора руки развязываются полностью. А со всеми ключикамии для линкера возможно получить кумулятивный эффект, под кодовым названием "без говNа":) И тут единственное, что может сохранить обращения к переменной это volatile и ничто более. Повтарюсь, не стоит сюда притягивать за уши static.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|