如何声明使用 malloc 创建的数组在 c++ 中是易失性的

发布于 2024-08-22 12:11:52 字数 235 浏览 5 评论 0原文

我认为以下内容会给我 10 个易失性整数

volatile int foo[10];

但是,我不认为以下内容会做同样的事情。

volatile int* foo;
foo = malloc(sizeof(int)*10);

如果我对此以及如何使用 malloc 获得易失性项目数组有误,请纠正我。

谢谢。

I presume that the following will give me 10 volatile ints

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.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

两相知 2024-08-29 12:11:52
int volatile * foo;

从右向左读“foo 是一个指向 易失性 int 的指针”,

因此无论您通过 foo 访问什么 int,该 int 都将是易失性的。

PS

int * volatile foo; // "foo is a volatile pointer to an int"

!=

volatile int * foo; // foo is a pointer to an int, volatile

意思 foo 是不稳定的。第二种情况实际上只是一般从右到左规则的遗留。
要吸取的教训是养成使用

char const * foo;

而不是更常见的

const char * foo;

习惯,如果您想要更复杂的东西,例如“指向函数的指针返回指向 int 的指针”,以使其有意义。

PS,这是一个大问题(也是我添加答案的主要原因):

我注意到您将“多线程”作为标签包含在内。您是否意识到 volatile 对于多线程几乎没有什么好处?

int volatile * foo;

read from right to left "foo is a pointer to a volatile int"

so whatever int you access through foo, the int will be volatile.

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

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.

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?

﹏半生如梦愿梦如真 2024-08-29 12:11:52
volatile int* foo;

是要走的路。 易失性类型限定符的工作方式与const类型限定符类似。如果您想要一个指向整数常量数组的指针,您可以编写:

const int* foo;

而 是

int* const foo;

指向本身可以更改的整数的常量指针。 易失性的工作原理相同。

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 int* foo;

whereas

int* const foo;

is a constant pointer to an integer that can itself be changed. volatile works the same way.

峩卟喜欢 2024-08-29 12:11:52

是的,那会起作用的。实际的易失性内存没有什么不同。它只是告诉编译器如何与该内存交互的一种方法。

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.

木有鱼丸 2024-08-29 12:11:52

我认为第二个声明指针是易失性的,而不是它指向的内容。为此,我认为应该是

int * volatile foo;

这种语法可以被 gcc 接受,但我遇到了麻烦说服自己它做了任何不同的事情。

我发现了与 gcc -O3 的区别(全面优化)。对于这个(愚蠢的)测试代码:

volatile int  v [10];
int * volatile p;

int main (void)
{
        v [3] = p [2];
        p [3] = v [2];
        return 0;
}

使用易失性,并省略不会改变的(x86)指令:

    movl    p, %eax
    movl    8(%eax), %eax
    movl    %eax, v+12
    movl    p, %edx
    movl    v+8, %eax
    movl    %eax, 12(%edx)

没有易失性,它会跳过重新加载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

经过更多的科学实验试图找出差异,我的结论是没有差异。易失性关闭与变量相关的所有优化,该变量将重用随后设置的值。至少使用 x86 gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-33)。 :-)

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.

I found a difference with gcc -O3 (full optimization). For this (silly) test code:

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:

    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:

    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). :-)

静水深流 2024-08-29 12:11:52

非常感谢 wallyk,我能够使用他的方法设计一些代码来生成一些程序集,以向自己证明不同指针方法之间的差异。

使用代码:并使用 -03 进行编译,

int main (void)
{
        while(p[2]);
        return 0;
}

当 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

请注意,L6 的唯一指令是转到 L6。

==

当 p 在这里是易失性指针时

int * volatile p;
==============
L3:
        movq    _p(%rip), %rax
        movl    8(%rax), %eax
        testl   %eax, %eax
        jne     L3
        xorl    %eax, %eax
        leave
        ret 

,指针 p 在每次循环迭代时都会重新加载,因此数组项也会重新加载。但是,如果我们想要一个易失性整数数组,则这是不正确的,因为这是可能的:

int* volatile p;
..
..
int* j;
j = &p[2];
while(j);

并且会导致循环在多线程程序中无法终止。

==

最后,这是正确的解决方案,正如托尼很好地解释的那样。

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 

在这种情况下,p[2] 的地址保存在寄存器值中,而不是从内存中加载,但 p[2] 的值会在每个循环周期从内存中重新加载。

另请注意,这

int volatile * p;
..
..
int* j;
j = &p[2];
while(j);

会产生编译错误。

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.

using the code: and compiling with -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.

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.

==

when p is volatile pointer

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:

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.

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.

also note that

int volatile * p;
..
..
int* j;
j = &p[2];
while(j);

will generate a compile error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文