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

Вопрос к знатокам С.

Чтение из переменной очевидно, когда оно стоит справа от знака присваивания.
К слову: совершенно неочевидно, что занесение значения в переменную слева от знака присваивания является лишь побочным эффектом опрератора "=", но это так и есть.

1) Согласно стандарту языка для чтения volatile переменной var достаточно написать

var;

Кому интересно, могу подкрепить это цитатами из стандарта.

Очень интересно. ИАР для АРМов, версии 4.30 точно (более старшие не проверял), с легкостью выкидывает такие обращения. ReAl объяснил это мутностью стандарта в этой части. Самому искать было лень. Но раз вы предлагаете найти - с удовольствием почитаю цитаты.
- бороться с предупреждениями компилятора при присваивании вспомогательной переменной

dummy = var;

Все встречавшиеся мне компиляторы убирали предупреждение при добавлении строчки dummy = dummy;

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


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

Очень интересно. ИАР для АРМов, версии 4.30 точно (более старшие не проверял), с легкостью выкидывает такие обращения.

Любой вменяемый компилятор выкидывает, но ЕСЛИ НЕ volatile. В данном случае это volatile, а не для volatile - выкидывает правильнно, ибо пустое и бессмысленное действие.

ReAl объяснил это мутностью стандарта в этой части.

Никакой мутности в отношении volatile переменных в C99 нет.

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


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

Любой вменяемый компилятор выкидывает, но ЕСЛИ НЕ volatile.
Вот сейчас специально поставлю ИАР и приведу листинг. Именно volatile переменную. Момент...

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


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

Все встречавшиеся мне компиляторы убирали предупреждение при добавлении строчки dummy = dummy;

Наиблее часто встречающийся :( с "финтами", но безграмотный вариант :(. Однозначный и независимый от компилятора и опимизации:

(void)dummy;

Вот сейчас специально поставлю ИАР и приведу листинг. Именно volatile переменную. Момент...

Не стоит :). Не получится.

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


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

Не стоит :). Не получится.
Если бы не получалось, я бы в эту ветку не писал:

 

 

Пожалуйста:

OS_INTERRUPT void Timer_ISR()
{
    OS::TISRW ISRW;

    T1IR;   // = T1IR;                    // clear int flag
    IO0SET = (1 << 29);

На строку с комментарием предупреждение: Warning[Pe174]: expression has no effect D:\Projects\Req\scmRTOS\Samples\LPC2xxx\1-EventFlag\Src\main.cpp 108

#######################################################################
#######
#                                                                            #
# IAR ARM ANSI C/C++ Compiler V4.30A/W32 EVALUATION    21/Oct/2008  23:47:48 #
# Copyright 1999-2005 IAR Systems. All rights reserved.                      #
#                                                                            #
#    Cpu mode        =  interwork                                            #
#    Endian          =  little                                               #
#    Stack alignment =  4                                                    #
#    Source file     =  D:\Projects\Req\scmRTOS\Samples\LPC2xxx\1-EventFlag\ #
#                       Src\main.cpp                                         #
#    Command line    =  D:\Projects\Req\scmRTOS\Samples\LPC2xxx\1-EventFlag\ #
#                       Src\main.cpp -D LPC2119 -lCN                         #
#                       D:\Projects\Req\scmRTOS\Samples\LPC2xxx\1-EventFlag\ #
#                       List\ -o D:\Projects\Req\scmRTOS\Samples\LPC2xxx\1-E #
#                       ventFlag\Obj\ -s9 --debug --cpu_mode thumb --endian  #
#                       little --cpu ARM7TDMI-S --stack_align 4 --interwork  #
#                       -e --fpu None --eec++ --dlib_config                  #
#                       D:\Programs\IAR\arm\LIB\dl4tptinl8n.h -I             #
#                       D:\Projects\Req\scmRTOS\Samples\LPC2xxx\1-EventFlag\ #
#                       Src\ -I D:\Projects\Req\scmRTOS\Samples\LPC2xxx\1-Ev #
#                       entFlag\..\scmRTOS\Common\ -I                        #
#                       D:\Projects\Req\scmRTOS\Samples\LPC2xxx\1-EventFlag\ #
#                       ..\scmRTOS\ARM7\ -I D:\Programs\IAR\arm\INC\         #
#    List file       =  D:\Projects\Req\scmRTOS\Samples\LPC2xxx\1-EventFlag\ #
#                       List\main.lst                                        #
#    Object file     =  D:\Projects\Req\scmRTOS\Samples\LPC2xxx\1-EventFlag\ #
#                       Obj\main.r79                                         #
#                                                                            #
#                                                                            #
##############################################################################
.........................
  \                                 In segment DATA_AN, at 0xe0008000
  \   <unnamed> volatile __data _A_T1IR
  \                     _A_T1IR:
  \   00000000                      DS8 4
.........................
   104          OS_INTERRUPT void Timer_ISR()
   105          {
  \                     ??Timer_ISR:
  \   00000000   04E04EE2           SUB         LR,LR,#+0x4
  \   00000004   1F502DE9           STMDB       SP!,{R0-R4,R12,LR}  ;; Push
   106              OS::TISRW ISRW;
  \   00000008   70409FE5           LDR         R4,??Timer_ISR_1   ;; Kernel
  \   0000000C   1400D4E5           LDRB        R0,[R4, #+0x14]
  \   00000010   010080E2           ADD         R0,R0,#+0x1
  \   00000014   1400C4E5           STRB        R0,[R4, #+0x14]
   107          
   108              T1IR;   // = T1IR;                    // clear int flag
   109              IO0SET = (1 << 29);
  \   00000018   4E02A0E3           MOV         R0,#-536870908
  \   0000001C   A00B80E3           ORR         R0,R0,#+0x28000
  \   00000020   8015A0E3           MOV         R1,#+0x20000000
  \   00000024   001080E5           STR         R1,[R0, #+0]

Компилятор не такой и старый, сильно моложе чем C99 не говоря уже о C89:

IAR C/C++ Compiler for ARM

4.30A Evaluation (4.30.1.237)

D:\Programs\IAR\arm\bin\iccarm.exe

09.02.2005 21:13:44, 9539584 bytes

Поэтому и хочется увидеть цитату из стандарта. А самому искать лень ;) GCC даже в версии 3.2.3 от 2003(?) года не выкидывает.

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


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

На строку с комментарием предупреждение: Warning[Pe174]: expression has no effect

Это типичное сообщение при выкидывании не volatile переменной. Просто T1IR неведомо как описан.

Давай чистый эксперимент.

volatile int dummy = 0;
.....
function()
{
dummy;

Поскольку я пишу на "С" уже лет 20, именно так, в том числе и под IAR, года 4, то в результате СИШНОГО КОМПИЛЯТОРА я более, чем уверен.

 

В догонку:

##############################################################################
#                                                                            #
# IAR ARM ANSI C/C++ Compiler V4.42A/W32               22/Oct/2008  01:13:05 #
# Copyright 1999-2005 IAR Systems. All rights reserved.                      #
#                                                                            #
#    Cpu mode        =  arm                                                  #
#    Endian          =  little                                               #
#    Stack alignment =  8                                                    #
#    Source file     =  D:\ARM_WORK\auc\MAIN\fiqhandl.c                      #
#    Command line    =  D:\ARM_WORK\auc\MAIN\fiqhandl.c -D LPC2000_IAR -lC   #
#                       D:\ARM_WORK\auc\Works_Kernel\List\ -lA               #
#                       D:\ARM_WORK\auc\Works_Kernel\List\ --remarks -o      #
#                       D:\ARM_WORK\auc\Works_Kernel\Obj\ -s9 --cpu_mode     #
#                       arm --endian little --cpu ARM7TDMI-S --stack_align   #
#                       8 --warnings_affect_exit_code                        #
#                       --no_path_in_file_macros --migration_preprocessor_ex #
#                       tensions -e --require_prototypes --fpu None          #
#                       --dlib_config "D:\IAR\Embedded                       #
#                       Workbench\arm\LIB\dl4tpannl8n.h" -I                  #
#                       D:\ARM_WORK\auc\..\COMMON\RTOS\portable\IAR\LPC2000\ #
#                        -I D:\ARM_WORK\auc\..\COMMON\RTOS\include\ -I       #
#                       D:\ARM_WORK\auc\..\COMMON\include\ -I                #
#                       D:\ARM_WORK\auc\main\include\ -I "D:\IAR\Embedded    #
#                       Workbench\arm\INC\" --inline_threshold=8             #
#    List file       =  D:\ARM_WORK\auc\Works_Kernel\List\fiqhandl.lst       #
#    Object file     =  D:\ARM_WORK\auc\Works_Kernel\Obj\fiqhandl.r79        #
#                                                                            #
#                                                                            #
##############################################################################

D:\ARM_WORK\auc\MAIN\fiqhandl.c
      1          
      2          #include <stdlib.h>
      3          #include "RTOS.h"

   \                                 In segment DATA_AN, at 0xe01fc140
   \   union <unnamed> volatile __data _A_EXTINT
   \                     _A_EXTINT:
   \   00000000                      DS8 4
      4          #include "fiqhandl.h"
      5          

   \                                 In segment DATA_Z, align 4, align-sorted
      6          volatile int dummy1;
   \                     dummy1:
   \   00000000                      DS8 4

   \                                 In segment DATA_Z, align 4, align-sorted
      7                   int dummy2;
   \                     dummy2:
   \   00000000                      DS8 4
      8          
      9          //---------------------------------------------------------------------------
     10          //
     11          //---------------------------------------------------------------------------

   \                                 In segment CODE, align 4, keep-with-next
     12          __fiq __arm void FIQ_ISR_handler(void)
     13          {
     14          
     15              dummy1;
   \                     FIQ_ISR_handler:
   \   00000000   14809FE5           LDR      R8,??FIQ_ISR_handler_0 ;; dummy1
   \   00000004   008098E5           LDR      R8,[R8, #+0]
     16              dummy2;
                     ^
Warning[Pe174]: expression has no effect
     17                 
     18

Оба варианта - c выкидыванием и без.

Более старях компиляторов не держу, но если что, то и на самом старом и кривом имеющимся у меня BCC 3.1 будет тоже самое. Ибо вариантов нет.

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


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

Попробовал на древнем:

# IAR Atmel AVR C/EC++ Compiler V3.20C/W32, Evaluation Version 22/Oct/2008 01:26:48 #

Тоже всё ок:

volatile unsigned char my_dummy;
void main(void)
{    
    my_dummy;
}
//==================================================== листинг:
     85          my_dummy;
   \   00000004   ....                       LDI     R26,LOW(??statetext)
   \   00000006   ....                       LDI     R27,(??statetext) >> 8
   \   00000008   01FD                       MOVW    R31 : R30,R27 : R26
   \   0000000A   8501                       LDD     R16,Z+9

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


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

Это типичное сообщение при выкидывании не volatile переменной. Просто T1IR неведомо как описан.
Я специально дал вырезку из листинга, в которой он сам эту переменную описывает как volatile:
   \                                 In segment DATA_AN, at 0xe0008000
   \   <unnamed> volatile __data _A_T1IR
   \                     _A_T1IR:
   \   00000000                      DS8 4

По поводу типичности сообщений один человек очень красиво написал на AVRFreaks:

In the case of warnings, the answer never lies in the C standard.

The C standard does not require any warnings.

We are trying to read the minds of the gods.

As a rule, a compiler issues a warning when you have done something that is allowed, but the compiler suspects might not be what you intended.

 

Давай чистый эксперимент.
Не вопрос:
volatile int dummy = 0;
void function()
{
    dummy;
}
//---------------------------------------------------------------------------
OS_INTERRUPT void Timer_ISR()
{
    OS::TISRW ISRW;

    T1IR;   // = T1IR;                    // clear int flag

Warning[Pe174]: expression has no effect D:\Projects\Req\scmRTOS\Samples\LPC2xxx\1-EventFlag\Src\main.cpp 106

Warning[Pe174]: expression has no effect D:\Projects\Req\scmRTOS\Samples\LPC2xxx\1-EventFlag\Src\main.cpp 113

Поскольку я пишу на "С" уже лет 20, именно так, в том числе и под IAR, года 4, то в результате СИШНОГО КОМПИЛЯТОРА я более, чем уверен.
Я не хочу спорить. ИАР вполне себе сишный компилятор и становится все лучше год от года. Я лишь хочу разобраться - это была бага или есть фича. Если стандарт описывает поведение однозначно - бага. Если нет - фича, и каждую версию каждого компилятора надо будет проверять на необходимость workaround с временной переменной, что я и делаю пока не разобрался в этом вопросе досконально. И как ни крути, хоть вариант без временной переменной красив, но, как видим, не всегда работает. А вариант с временной переменной работает всегда. Следовательно надо разобраться, кто виноват в непортируемости - компилятор, который не соответствует стандарту или программист, понадеявшийся на нерегламентируемое стандартом поведение компилятора.
В догонку:
В новой версии behaviour изменился :)

 

Все, спать. Иначе придется самим в стандарте копаться ;)

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


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

ИАР вполне себе сишный компилятор и....

Тем не менее, ты компилишь П Л Ю С О В Ы М (точнее недоплюсовым :( ) компилятором, почему-то рассуждая о C99. Кроме того, ты получил более, чем вменяемый Warning.

...но, как видим, не всегда работает

Я бы поверил, в баг конкретного компилятора, если-бы не работал и с этой версией компилятора, причем гарантированно, многократно и постоянно использовал и использую, как минимум:

SSPDR;

для очистки FIFO SSP при полудуплексной передаче.

Хидеры традиционно использую самописные.

По поводу типичности сообщений один человек очень красиво написал на AVRFreaks:

В данном случае я говорю о типичном собщении совершенно конкретного компилятора.

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


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

Тем не менее, ты компилишь ПЛЮСОВЫМ компилятором.
В точку. Попробовал без плюсов - варнинга нет, чтение есть. Придется штудировать и плюсовый стандарт :crying: Не думал, что в этом вопросе он отличается от неплюсового.

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


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

Не думал, что в этом вопросе он отличается от неплюсового.

Не думаю, что отличается, поскольку это совершенно естественное-разумное поведение. Любое другое не берусь даже хоть как-то объяснить...Полубаг "старого" компилятора :( ?

 

P.S.

Попробовал. Любая версия V4-V5 плюсовых компиляторов от IAR выдает warning. Странно.

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


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

Однозначный и независимый от компилятора и опимизации:

(void)dummy;

Вы знаете, попробовал - не работает. Все равно ворнинг. IAR AVR 4.3 (EEC++). Код:

byte dummy;
dummy = UDR0;
dummy = UDR0;
dummy = UDR0;
(void) dummy;

UDR0 - из стандартного иаровского хидера:

SFR_B_R(0x1F,   AVR) Expands to:
* __io union {
*             unsigned char AVR;                 // The sfrb as 1 byte
*             struct {                           // The sfrb as 8 bits
*                     unsigned char AVR_Bit0:1,
*                                   AVR_Bit1:1,
*                                   AVR_Bit2:1,
*                                   AVR_Bit3:1,
*                                   AVR_Bit4:1,
*                                   AVR_Bit5:1,
*                                   AVR_Bit6:1,
*                                   AVR_Bit7:1;
*                    };
*            } @ 0x1F;

SFR_B_R(0x0C,   UDR0)     /* USART0 I/O Data Register */

Ворнинг давится только dummy=dummy :)

 

PS начал читать тему - думал можно будет избавиться от этого некрасивого кода :(

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


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

Вы знаете, попробовал - не работает. Все равно ворнинг. IAR AVR 4.3 (EEC++). Код:

byte dummy;
dummy = UDR0;
dummy = UDR0;
dummy = UDR0;
(void) dummy;

UDR0 - из стандартного иаровского хидера:

...

Ворнинг давится только dummy=dummy :)

 

PS начал читать тему - думал можно будет избавиться от этого некрасивого кода :(

В Вашем случае прочитать UDR0 без dummy можно и так:

    if (UDR0);

Правда не знаю насколько это читабельно смотрится. На любителя. В плюсах работает и я уже привык.

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


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

IAR AVR 4.3 (EEC++).....

Ну что я могу сказать - много значит cтранностей в IARовском недоплюсовом компиляторе :(. Подчеркиваю еще раз ПЛЮСОВОМ, а тема начинслась как C/C99.

Если

var;

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

(void)var;

ввиде макросика USED(var) - в процессе написания ну очень часто.

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

В оправдание плюсового IAR, могу сказать только то, что warnings он тем не менее генерит...

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


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

ReAl объяснил это мутностью стандарта в этой части. Самому искать было лень.
Ой, не помню... Кажется, разночтение было на тему - обязательно ли в цепочке

int a;
volatile int v;
a = v = 0;

для записи в a зачитывать из v. Согласно стандарту значением присваивающего выражения есть значение, которое будет записано в левую часть после присваивания.

Я утверждал, что в случае volatile-переменной значение неизвестно и нужно перезачитать.

Но какой-то компилятор радостно в таком случае явно писал нули во все переменные, что на мой взгляд неправильно. В каком-то обсуждении (RU.C-CPP или ещё где-то) было сказано, что смысл строки стандарта не "что там будет сидеть после записи", а "что туда будет записано", а это не зависит от volatile-ности. Я не стал разбираться дальше, "юридический английский" у меня не настолько... :-(

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

т.е. не использовал while( (volatile_var = var) ), function( volatile_var = var), return (volatile_var = var);

 

Однако считаю, что в случае отдельно стоящей volatile-переменной в духе

 UDR;

компилятор должен провести все действия, необходимые для вычисления выражения (в данном случае только прочесть переменую, в случае с UDR+1; - прочесть и прибавить единицу), а только потом обнаружить, что результат-то никому не нужен и начать оптимизатором "отматывать" назад ненужные действия - пока не упрётся в запрет, поставленный квалификатором volatile. Т.е. чтение volatile-переменной должно остаться. Если какой-то компилятор этого не делает (это тоже, кажется, где-то в аське обсуждалось), то надо внимательно ещё раз прочесть стандарт и попытаться поругаться.

 

 

 

Без финтов - это отлично, но!!! - очень непривычно. Чтение из переменной очевидно, когда оно стоит справа от знака присваивания. И когда этот знак опущен это и вызывает недоумение и неприятие.
А многие не понимают указателей.

А у многих вызывает недоумение запись

 value = ( flag ? sin : cos)(x);

несмотря на то, что она, на мой взгялд, гораздо более читабельна, чем алгол-68

value := if flag then sin else cos fi (x)

 

Если из С повыбрасывать всё то, что вызывает недоумение у новичков, то что останется?

 

volatile int x;
...
    x ? : x;

Прочесть x, если он равен нулю - прочесть его ещё раз. С прочитанными значениями больше ничего не делать.

 

Коллеге zltigo респект за неординарный подход.
Подход правильный, называется "знать инструмент, которым пользуешся".

 

 

Итак, итоги:

...

2) Очевидно, что такой код не проходит тест "даже моя бабушка поймёт, что это значит". Другими словами, читаемость кода страдает.

Читаемость кода завиит от подготовки читающего. Так можно дойти и до "отмены" ++ и переходу от ++i к i = i + 1; (во всяком случае побыстрее запретить применение i++, так как это вообще непонятно).

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

 

На строку с комментарием предупреждение: Warning[Pe174]: expression has no effect D:\Projects\Req\scmRTOS\Samples\LPC2xxx\1-EventFlag\Src\main.cpp 108
Странно...

Всё-таки странно.

Может всё-же пройтись ещё по стандарту и попробовать с ними поругаться?

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


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

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

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

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

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

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

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

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

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

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