可变变量作为函数的参数 [英] volatile variables as argument to function

查看:30
本文介绍了可变变量作为函数的参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有这个代码:

typedef volatile int COUNT;       

COUNT functionOne( COUNT *number );

int  functionTwo( int *number );

我无法摆脱一些警告..

I can't get rid of some warnings..

我在 functionOne 原型上收到这个警告 1

I get this warning 1 at functionOne prototype

[警告] 类型限定符被忽略函数返回类型

[Warning] type qualifiers ignored on function return type

并且我收到此警告 2,无论我在哪里使用 COUNT pointer 参数而不是 int 指针调用 functionTwo

and I get this warning 2, wherever I call functionTwo with a COUNT pointer argument instead of an int pointer

[警告] cast 丢弃限定符来自指针目标类型

[Warning] cast discards qualifiers from pointer target type

显然变量/指针不能被强制转换"为易失性/非易失性..但每个参数也必须指定为易失性?那么如果已经为非易失性变量定义了任何库函数,我该如何使用它呢?

obviously variables/pointers can't be "cast" to volatile/un-volatile.. but every arguments must be specified as volatile too? so how can I use any library function if it's already defined for non-volatile variable?

编辑:使用 gcc -std=c99 -pedantic -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wextra -Wstrict-prototypes -Wmissing-prototypes ...

编辑:在 Jukka Suomela 建议之后,这是警告二的代码示例

EDIT: After Jukka Suomela advice this is a code sample for warning two

typedef volatile int COUNT;       

static int functionTwo(int *number) {
    return *number + 1;
}

int main(void) {
    COUNT count= 10;
    count = functionTwo(&count);
    return 0;
}

推荐答案

volatile 关键字旨在应用于表示存储的对象而不是函数.从函数返回 volatile int 没有多大意义.函数的返回值不会被优化掉(内联函数可能例外,但这完全是另一种情况......),并且没有外部参与者会修改它.当函数返回时,它将返回值的副本传递给调用函数.volatile 对象的副本本身不是 volatile.因此,尝试返回 volatile int 将导致一个副本,将其转换为非易失性 int,这就是触发编译器消息的原因.返回 volatile int* 可能有用,但不是 volatile int.

The volatile keyword was designed to be applied to objects that represent storage and not to functions. Returning a volatile int from a function does not make much sense. The return value of a function will not be optimized away (with the possible exception of inlined functions, but that's another case altogether...), and no external actor will be modifying it. When a function returns, it passes a copy of the return value to the calling function. A copy of a volatile object is not itself volatile. Therefore, attempting to return a volatile int will result in a copy, casting it down to a non-volatile int, which is what is triggering your compiler messages. Returning a volatile int* might be useful, but not a volatile int.

将对象按值传递给函数会生成对象的副本,因此使用 volatile int 作为函数参数必然涉及忽略限定符的转换.按地址传递 volatile 是完全合理的,但不能按值传递.

Passing an object by value into a function makes a copy of the object, thus using a volatile int as a function parameter necessarily involves a conversion that ignores a qualifier. Passing a volatile by address is perfectly reasonable, but not by value.

根据 C 规范,volatile 的行为完全依赖于实现,所以 YMMV.

According to the C spec, the behavior of volatile is completely implementation-dependent, so YMMV.

您是否以这种方式使用 volatile 来试图击败某种编译器优化?如果是这样,可能有更好的方法.

Are you using volatile in this way to try to defeat some sort of compiler optimization? If so, there is probably a better way to do it.

考虑到您的问题的更新,您似乎可以以不同的方式解决这个问题.如果您试图击败编译器优化,为什么不采取直接方法并简单地告诉编译器不要优化某些东西?您可以使用 #pragma GCC 优化__attribute__((optimize)) 给出函数的特定优化参数.例如, __attribute__((optimize(0))) 应该禁用给定函数的所有优化.这样,您可以保持数据类型的非易失性并避免您遇到的类型问题.如果禁用所有优化有点过分,您还可以使用该属性/pragma 打开或关闭各个优化选项.

Taking into account the updates to your question, it appears that you may be able to approach this in a different way. If you are trying to defeat compiler optimizations, why not take the direct approach and simply tell the compiler not to optimize some things? You can use #pragma GCC optimize or __attribute__((optimize)) to give specific optimization parameters for a function. For example, __attribute__((optimize(0))) should disable all optimizations for a given function. That way, you can keep your data types non-volatile and avoid the type problems you are having. If disabling all optimizations is a bit too much, you can also turn individual optimization options on or off with that attribute/pragma.

我能够在没有任何警告或错误的情况下编译以下代码:

I was able to compile the following code without any warnings or errors:

static int functionTwo(int *number) {
    return *number + 1;
}

typedef union {
                int i;
    volatile    int v;
} fancy_int;

int main(void) {
    fancy_int count;
    count.v = 10;
    count.v = functionTwo(&count.i);
    return 0;
}

这个hack技术"可能有一些奇怪的副作用,所以在生产使用之前彻底测试它.这很可能与直接将地址转换为 (int*) 没有什么不同,但它不会触发任何警告.

This hack"technique" probably has some kind of odd side-effects, so test it thoroughly before production use. It's most likely no different than directly casting the address to a (int*), but it doesn't trigger any warnings.

这篇关于可变变量作为函数的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆