Como faço para declarar uma matriz criada usando malloc para ser volátil em c + +

Eu presumo que o seguinte me dará 10 ints voláteis

volatile int foo[10]; 

No entanto, não acho que o seguinte faça a mesma coisa.

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

Por favor, corrija-me se eu estiver errado sobre isso e como posso ter uma série volátil de itens usando malloc.

Obrigado.

 int volatile * foo; 

leia da direita para a esquerda “foo é um ponteiro para um int volátil”

Assim, seja qual for o int que você acessar através do foo, o int será volátil.

PS

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

==

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

Significado foo é volátil. O segundo caso é realmente apenas uma sobra da regra geral da direita para a esquerda. A lição a ser aprendida é adquirir o hábito de usar

 char const * foo; 

em vez do mais comum

 const char * foo; 

Se você quer coisas mais complicadas como “ponteiro para funcionar retornando ponteiro para int” para fazer algum sentido.

PS, e isso é um biggy (e a principal razão pela qual estou adicionando uma resposta):

Observo que você incluiu “multithreading” como tag. Você percebe que volátil faz pouco / nada de bom em relação ao multithreading?

 volatile int* foo; 

é o caminho a percorrer. O qualificador de tipo volátil funciona exatamente como o qualificador do tipo const . Se você quisesse um ponteiro para um array constante de inteiro, você escreveria:

 const int* foo; 

enquanto que

 int* const foo; 

é um ponteiro constante para um inteiro que pode ser alterado. volátil funciona da mesma maneira.

Sim, isso vai funcionar. Não há nada diferente sobre a memory real que é volatile . É apenas uma maneira de dizer ao compilador como interagir com essa memory.

Eu acho que o segundo declara que o ponteiro é volátil, não o que ele aponta. Para conseguir isso, acho que deveria ser

 int * volatile foo; 

Essa syntax é aceitável para o gcc , mas estou tendo problemas em convencer-me de que faz algo diferente.

Eu encontrei uma diferença com o gcc -O3 (otimização total). Para este código de teste (bobo):

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

Com instruções volatile e omitindo (x86) que não mudam:

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

Sem volátil, ele pula o recarregamento de 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 

Depois de muitos outros experimentos científicos tentando encontrar uma diferença, concluo que não há diferença. volatile desativa todas as otimizações relacionadas à variável que reutilizaria um valor definido subseqüentemente. Pelo menos com x86 gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-33). 🙂

Muito obrigado a wallyk, eu era capaz de conceber algum código usar seu método para gerar alguma assembly para provar a mim mesmo a diferença entre os diferentes methods de ponteiro.

usando o código: e compilando com -03

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

Quando p é simplesmente declarado como ponteiro, ficamos presos em um loop que é impossível sair. Note que se este fosse um programa multiencadeado e um thread diferente escrevesse p [2] = 0, então o programa sairia do loop while e terminaria normalmente.

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

observe que a única instrução para L6 é ir para L6.

==

quando p é ponteiro volátil

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

aqui, o ponteiro p é recarregado em cada iteração de loop e, como conseqüência, o item da matriz também é recarregado. No entanto, isso não estaria correto se quiséssemos uma matriz de inteiros voláteis, pois isso seria possível:

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

e resultaria no loop que seria impossível terminar em um programa multithread.

==

finalmente, esta é a solução correta como tony bem explicado.

 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 

Neste caso, o endereço de p [2] é mantido no valor de registro e não é carregado da memory, mas o valor de p [2] é recarregado da memory em cada ciclo de loop.

Observe também que

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

irá gerar um erro de compilation.