I presume that the following will give me 10 volatile ints
我想下面的内容会给我10个挥发油
volatile int foo[10];
However, I don't think the following will do the same thing.
然而,我不认为下面的方法会起到同样的作用。
volatile int* foo;
foo = malloc(sizeof(int)*10);
Please correct me if I am wrong about this and how I can have a volatile array of items using malloc.
如果我错了,请纠正我,我如何使用malloc有一个不稳定的数组。
Thanks.
谢谢。
5 个解决方案
#1
12
int volatile * foo;
read from right to left "foo is a pointer to a volatile int"
从右到左读“foo是一个指向可变整数的指针”
so whatever int you access through foo, the int will be volatile.
无论你通过foo访问什么int数,它都是可变的。
P.S.
注:
int * volatile foo; // "foo is a volatile pointer to an int"
==
= =
volatile int * foo; // foo is a pointer to an int, volatile
Meaning foo is volatile. The second case is really just a leftover of the general right-to-left rule. The lesson to be learned is get in the habit of using
意义foo是不稳定的。第二种情况实际上是一般的从右到左规则的残余。要吸取的教训是养成使用的习惯
char const * foo;
instead of the more common
而不是更常见的
const char * foo;
If you want more complicated things like "pointer to function returning pointer to int" to make any sense.
如果你想要更复杂的东西,比如“指针指向函数返回指针到int”,这是有意义的。
P.S., and this is a biggy (and the main reason I'm adding an answer):
注:,这是一个很大的(也是我增加答案的主要原因):
I note that you included "multithreading" as a tag. Do you realize that volatile does little/nothing of good with respect to multithreading?
我注意到您包含了“多线程”作为标记。您是否意识到volatile在多线程方面几乎没有什么好处?
#2
6
volatile int* foo;
is the way to go. The volatile type qualifier works just like the const type qualifier. If you wanted a pointer to a constant array of integer you would write:
这是条路。可变类型限定符与const类型限定符一样工作。如果你想要一个指针指向一个整数常量数组,你可以这样写:
const int* foo;
whereas
而
int* const foo;
is a constant pointer to an integer that can itself be changed. volatile works the same way.
是指向可更改的整数的常量指针。挥发物也是如此。
#3
3
Yes, that will work. There is nothing different about the actual memory that is volatile
. It is just a way to tell the compiler how to interact with that memory.
是的,工作。不稳定的实际内存没有什么不同。它只是告诉编译器如何与内存交互的一种方式。
#4
2
I think the second declares the pointer to be volatile, not what it points to. To get that, I think it should be
我认为第二个声明指针是不稳定的,而不是它指向的。为了得到这个,我认为它应该是
int * volatile foo;
This syntax is acceptable to gcc
, but I'm having trouble convincing myself that it does anything different.
这种语法对gcc来说是可以接受的,但是我很难让自己相信它有什么不同。
I found a difference with gcc -O3
(full optimization). For this (silly) test code:
我发现了gcc -O3(完全优化)的不同之处。对于这个(愚蠢的)测试代码:
volatile int v [10];
int * volatile p;
int main (void)
{
v [3] = p [2];
p [3] = v [2];
return 0;
}
With volatile
, and omitting (x86) instructions which don't change:
使用volatile和省略(x86)不更改的指令:
movl p, %eax
movl 8(%eax), %eax
movl %eax, v+12
movl p, %edx
movl v+8, %eax
movl %eax, 12(%edx)
Without volatile, it skips reloading p
:
无挥发性,漏装p:
movl p, %eax
movl 8(%eax), %edx ; different since p being preserved
movl %edx, v+12
; 'p' not reloaded here
movl v+8, %edx
movl %edx, 12(%eax) ; p reused
After many more science experiments trying to find a difference, I conclude there is no difference. volatile
turns off all optimizations related to the variable which would reuse a subsequently set value. At least with x86 gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-33). :-)
经过更多的科学实验试图找到不同之处,我认为没有区别。volatile关闭与变量相关的所有优化,这些优化将重用随后设置的值。至少使用x86 gcc (gcc) 4.1.2 20070925 (Red Hat 4.2 -33)。:-)
#5
1
Thanks very much to wallyk, I was able to devise some code use his method to generate some assembly to prove to myself the difference between the different pointer methods.
非常感谢wallyk,我能够设计一些代码,使用他的方法生成一些程序集来证明不同指针方法之间的区别。
using the code: and compiling with -03
使用代码:并使用-03编译。
int main (void)
{
while(p[2]);
return 0;
}
when p is simply declared as pointer, we get stuck in a loop that is impossible to get out of. Note that if this were a multithreaded program and a different thread wrote p[2] = 0, then the program would break out of the while loop and terminate normally.
当p被简单地声明为指针时,我们会被困在一个无法跳出的循环中。注意,如果这是一个多线程程序,而另一个线程写了p[2] = 0,那么该程序将跳出while循环并正常终止。
int * p;
============
LCFI1:
movq _p(%rip), %rax
movl 8(%rax), %eax
testl %eax, %eax
jne L6
xorl %eax, %eax
leave
ret
L6:
jmp L6
notice that the only instruction for L6 is to goto L6.
注意,L6的唯一指令是转到L6。
==
when p is volatile pointer
当p是挥发性指针时
int * volatile p;
==============
L3:
movq _p(%rip), %rax
movl 8(%rax), %eax
testl %eax, %eax
jne L3
xorl %eax, %eax
leave
ret
here, the pointer p gets reloaded each loop iteration and as a consequence the array item also gets reloaded. However, this would not be correct if we wanted an array of volatile integers as this would be possible:
这里,指针p被重新加载每个循环迭代,因此数组项也被重新加载。但是,如果我们想要一个易失性整数数组,这是不正确的,因为这是可能的:
int* volatile p;
..
..
int* j;
j = &p[2];
while(j);
and would result in the loop that would be impossible to terminate in a multithreaded program.
并且会导致在多线程程序中不可能终止的循环。
==
finally, this is the correct solution as tony nicely explained.
最后,正如tony解释的那样,这是正确的解决方案。
int volatile * p;
LCFI1:
movq _p(%rip), %rdx
addq $8, %rdx
.align 4,0x90
L3:
movl (%rdx), %eax
testl %eax, %eax
jne L3
leave
ret
In this case the the address of p[2] is kept in register value and not loaded from memory, but the value of p[2] is reloaded from memory on every loop cycle.
在这种情况下,p[2]的地址保持在寄存器值中,而不是从内存中加载,但是p[2]的值在每个循环中从内存中重新加载。
also note that
还要注意,
int volatile * p;
..
..
int* j;
j = &p[2];
while(j);
will generate a compile error.
将生成一个编译错误。
#1
12
int volatile * foo;
read from right to left "foo is a pointer to a volatile int"
从右到左读“foo是一个指向可变整数的指针”
so whatever int you access through foo, the int will be volatile.
无论你通过foo访问什么int数,它都是可变的。
P.S.
注:
int * volatile foo; // "foo is a volatile pointer to an int"
==
= =
volatile int * foo; // foo is a pointer to an int, volatile
Meaning foo is volatile. The second case is really just a leftover of the general right-to-left rule. The lesson to be learned is get in the habit of using
意义foo是不稳定的。第二种情况实际上是一般的从右到左规则的残余。要吸取的教训是养成使用的习惯
char const * foo;
instead of the more common
而不是更常见的
const char * foo;
If you want more complicated things like "pointer to function returning pointer to int" to make any sense.
如果你想要更复杂的东西,比如“指针指向函数返回指针到int”,这是有意义的。
P.S., and this is a biggy (and the main reason I'm adding an answer):
注:,这是一个很大的(也是我增加答案的主要原因):
I note that you included "multithreading" as a tag. Do you realize that volatile does little/nothing of good with respect to multithreading?
我注意到您包含了“多线程”作为标记。您是否意识到volatile在多线程方面几乎没有什么好处?
#2
6
volatile int* foo;
is the way to go. The volatile type qualifier works just like the const type qualifier. If you wanted a pointer to a constant array of integer you would write:
这是条路。可变类型限定符与const类型限定符一样工作。如果你想要一个指针指向一个整数常量数组,你可以这样写:
const int* foo;
whereas
而
int* const foo;
is a constant pointer to an integer that can itself be changed. volatile works the same way.
是指向可更改的整数的常量指针。挥发物也是如此。
#3
3
Yes, that will work. There is nothing different about the actual memory that is volatile
. It is just a way to tell the compiler how to interact with that memory.
是的,工作。不稳定的实际内存没有什么不同。它只是告诉编译器如何与内存交互的一种方式。
#4
2
I think the second declares the pointer to be volatile, not what it points to. To get that, I think it should be
我认为第二个声明指针是不稳定的,而不是它指向的。为了得到这个,我认为它应该是
int * volatile foo;
This syntax is acceptable to gcc
, but I'm having trouble convincing myself that it does anything different.
这种语法对gcc来说是可以接受的,但是我很难让自己相信它有什么不同。
I found a difference with gcc -O3
(full optimization). For this (silly) test code:
我发现了gcc -O3(完全优化)的不同之处。对于这个(愚蠢的)测试代码:
volatile int v [10];
int * volatile p;
int main (void)
{
v [3] = p [2];
p [3] = v [2];
return 0;
}
With volatile
, and omitting (x86) instructions which don't change:
使用volatile和省略(x86)不更改的指令:
movl p, %eax
movl 8(%eax), %eax
movl %eax, v+12
movl p, %edx
movl v+8, %eax
movl %eax, 12(%edx)
Without volatile, it skips reloading p
:
无挥发性,漏装p:
movl p, %eax
movl 8(%eax), %edx ; different since p being preserved
movl %edx, v+12
; 'p' not reloaded here
movl v+8, %edx
movl %edx, 12(%eax) ; p reused
After many more science experiments trying to find a difference, I conclude there is no difference. volatile
turns off all optimizations related to the variable which would reuse a subsequently set value. At least with x86 gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-33). :-)
经过更多的科学实验试图找到不同之处,我认为没有区别。volatile关闭与变量相关的所有优化,这些优化将重用随后设置的值。至少使用x86 gcc (gcc) 4.1.2 20070925 (Red Hat 4.2 -33)。:-)
#5
1
Thanks very much to wallyk, I was able to devise some code use his method to generate some assembly to prove to myself the difference between the different pointer methods.
非常感谢wallyk,我能够设计一些代码,使用他的方法生成一些程序集来证明不同指针方法之间的区别。
using the code: and compiling with -03
使用代码:并使用-03编译。
int main (void)
{
while(p[2]);
return 0;
}
when p is simply declared as pointer, we get stuck in a loop that is impossible to get out of. Note that if this were a multithreaded program and a different thread wrote p[2] = 0, then the program would break out of the while loop and terminate normally.
当p被简单地声明为指针时,我们会被困在一个无法跳出的循环中。注意,如果这是一个多线程程序,而另一个线程写了p[2] = 0,那么该程序将跳出while循环并正常终止。
int * p;
============
LCFI1:
movq _p(%rip), %rax
movl 8(%rax), %eax
testl %eax, %eax
jne L6
xorl %eax, %eax
leave
ret
L6:
jmp L6
notice that the only instruction for L6 is to goto L6.
注意,L6的唯一指令是转到L6。
==
when p is volatile pointer
当p是挥发性指针时
int * volatile p;
==============
L3:
movq _p(%rip), %rax
movl 8(%rax), %eax
testl %eax, %eax
jne L3
xorl %eax, %eax
leave
ret
here, the pointer p gets reloaded each loop iteration and as a consequence the array item also gets reloaded. However, this would not be correct if we wanted an array of volatile integers as this would be possible:
这里,指针p被重新加载每个循环迭代,因此数组项也被重新加载。但是,如果我们想要一个易失性整数数组,这是不正确的,因为这是可能的:
int* volatile p;
..
..
int* j;
j = &p[2];
while(j);
and would result in the loop that would be impossible to terminate in a multithreaded program.
并且会导致在多线程程序中不可能终止的循环。
==
finally, this is the correct solution as tony nicely explained.
最后,正如tony解释的那样,这是正确的解决方案。
int volatile * p;
LCFI1:
movq _p(%rip), %rdx
addq $8, %rdx
.align 4,0x90
L3:
movl (%rdx), %eax
testl %eax, %eax
jne L3
leave
ret
In this case the the address of p[2] is kept in register value and not loaded from memory, but the value of p[2] is reloaded from memory on every loop cycle.
在这种情况下,p[2]的地址保持在寄存器值中,而不是从内存中加载,但是p[2]的值在每个循环中从内存中重新加载。
also note that
还要注意,
int volatile * p;
..
..
int* j;
j = &p[2];
while(j);
will generate a compile error.
将生成一个编译错误。