2016-08-16 7 views
2

Я думаю, у меня есть сложный вопрос, но я уверен, что вы сможете мне помочь. Скажем, у меня есть функция, как это:Литейная изменчивая переменная в c

char my_function (int example); 

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

Сценарий 1:

Прототип char my_function (int example);

int a; 
volatile int b; 

my_function (a); // Everything is fine. 
my_function ((int)b); // Avoided the warning, by casting the variable and   saying it's no longer volatile. 

Сценарий 2:

Прототип char my_function (volatile int example);

int a; 
volatile int b; 

my_function(b); // Everything is fine. 
my_function((volatile int)a); // Avoided the warning, by casting 'a' saying that now it's volatile. 

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

+0

Возможный дубликат [изменчивых переменных как аргумент функции] (http://stackoverflow.com/questions/3303660/volatile-variables-as-argument-to-function) – kdopen

+0

Чтобы устранить основную причину, объявите 'my_function' с помощью параметр 'volatile' – kdopen

+1

' volatile' не является модификатором, а определителем. Модификаторов нет. И ваш вопрос непонятен. Хотя вы говорите иначе, ваш текст позволяет предположить, что вы не знаете, как работает «volatile». Пересмотрите свою книгу C или получите лучшую. И никогда не произносите выражение, пока не осознаете ** все ** последствия. У меня есть серьезные сомнения. – Olaf

ответ

2

Это действительно зависит от того, что my_functionделает с его аргументом.

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

volatile int a; 
int b; 
// ... 
b = a + 1; 
b = a + 2; 

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

Когда вы передаете volatile в функцию в качестве параметра, вы получаете только одну переменную read. Это может затем использоваться несколько раз в пределах функции (эффективно теряя природу volatile).

Помните, что C является передачей по значению. При вызове функции в качестве

my_function((int)b); // b is declared volatile 

Компилятор генерирует код для чтения b один раз в коде вызова, и нажать значение прочитанную в стек (обычно), а затем вызвать my_function. Затем эта копия ссылается на my_function как example, и независимо от того, как часто вы ссылаетесь на example, вы всегда будете получать одинаковое значение (даже если переменная b с тех пор неоднократно менялась).

Это может быть именно то, что вы хотите - сделайте снимок переменной и выполните несколько вычислений по ее значению.

Если это не то, что вы хотите, вам необходимо обратиться в указатель с соответствующими квалификациями volatile.

char my_function(volatile int *example); 

И назвать это таким образом:

my_function(&a); 
my_function(&b); 

Тогда ссылка *example внутри my_function.

+1

Это довольно бред какой то. Если переменная, которую вы ** передаете ** в функцию, должна быть 'volatile', вам нужно _declare переменную' volatile', а не использовать _expression_, которую вы используете для параметра 'volatile'. Я даже не вижу, как это изменит что-либо в коде, потому что вы передали выражение 'volatile', а затем присвойте результат не-« энергонезависимому »параметру. – Olaf

+0

Пример вашего указателя, хотя и действительный, совершенно другой, поскольку он не квалифицирует параметр 'volatile', а _object указывает на_. Указателем 'volatile' был бы' int * volatile p' и как мало используемый параметр 'int i'. – Olaf

+0

И это действительно «значение, на которое оно указывает», которое является изменчивым, а не указателем. – kdopen

1

Листинг фактически ничего не делает. В вызове my_function (b); код читает volatile int b. Именно там «волатильность» имеет значение во время чтения. Результат чтения уже является int, а не изменчивым int. Нет значений volatile int. Даже если бы были измененные значения int, передача его в my_function превращала бы его в простой int, как это делает cast.

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

+0

Это предупреждение было бы окончательно ошибочным. Неустойчивый определитель не является частью значения, но только lvalues ​​(как и все квалификаторы, см. 6.7.3p4). Такой компилятор подозрительно иметь другие недостатки. Я не уверен, что смогу доверять этой вещи, чтобы создать правильный код. – Olaf