2014-11-15 3 views
5

Можете ли вы помочь мне понять, почему компилятор дает мне эти сообщения об ошибках? Я считаю, что члены изменчивых объектов тоже нестабильны. Я имею в виду от here. Но он показывает, что если мы имеем структуру:Неустойчивая связанная ошибка в коде C++

struct someStruct 
{ 
    int d; 
}; 

А «р» определенный как:

volatile someStruct* volatile* p; 

&(*p)->d имеют следующий вид «Int * летучий *» вместо «летучего междунар * volatile * '. Ниже приведен фактический код, над которым я работаю.


Линия (отмечена ошибками 1 & 2), где компилятор выдает сообщение об ошибке:

#include <vector> 
#include <windows.h> 

using namespace std; 

struct ThreadInfo 
{ 
    bool bWaiting = false; 

    bool bWorking = false; 
}; 

struct lThreadInfo 
{ 
    ThreadInfo d; 
    lThreadInfo *pNextList = nullptr; 
} volatile *volatile lThreads(nullptr); 

thread_local ThreadInfo* currentThr(nullptr); 

void CreateThread_(void (*pFunc)(ThreadInfo*)) 
{ 
    volatile lThreadInfo* volatile* p = &lThreads; 

    for(; *p; p = &(*p)->pNextList); //**//error 1!** 

    *p = new lThreadInfo; 

    CreateThread(
      nullptr,     // default security attributes 
      0,      // use default stack size 
      (long unsigned int (*)(void*))pFunc,  // thread function name 
      &(*p)->d,   // argument to thread function  **//error 2!** 
      0,      // use default creation flags 
      nullptr); 
} 

Ошибки сообщениях являются следующим:

error 1: invalid conversion from 'lThreadInfo* volatile*' to 'volatile lThreadInfo* volatile*' [-fpermissive] 
error 2: invalid conversion from 'volatile void*' to 'LPVOID {aka void*}' [-fpermissive] 

Примечания: Я знаю, что летучие не имеют ничего общего с потокобезопасностью, так что не надо мне так говорить. Note1: Я использую компилятор mingw64 на окнах.

+0

Для второй ошибки вам понадобится 'const_cast', чтобы отключить' volatile' для вызова функции Windows API. Для первой ошибки член 'pNextList' также должен быть' volatile' (или удалить 'volatile' из' p'). – Niall

+0

Но не следует ли создавать объект с изменчивым спецификатором, автоматически также делает все его подвыходы? – AnArrayOfFunctions

+0

'lThreadInfo :: pNextList' имеет тип' lThreadInfo * '. Если у вас есть объект 'lThreadInfo', который является' volatile', например. 'lThreadInfo volatile o;', тогда 'o.pNextList' является' lThreadInfo * volatile'. Cv-квалификаторы всегда применяются к типу «outmost», а не к указанному типу. – dyp

ответ

2

pNextList, через volatile access-path, is volatile тоже. Но pNextList - это указатель . Точка имеет ту же квалификацию cv, что и раньше.

То есть, для

struct A 
{ 
    lThreadInfo* p; 
}; 

someStruct volatile* volatile* p; 
  • *p представляет собой объект типа someStruct volatile* volatile
  • (*p)->d представляет собой объект типа lThreadInfo* volatile.

Таким образом, в типе (*p)->d вы теряете летучий между lThreadInfo и *. [Expr.ref]/4:

Если E2 не является статическим членом данных и тип E1 является «CQ1 VQ1 X», а также тип E2 является «cq2 vq2T », Выражение обозначает именованный элемент объекта, обозначенный первым выражением . Если E1 является значением lvalue, то E1.E2 является lvalue; если E1 - значение x, то E1.E2 - значение xvalue; в противном случае это значение. Пусть обозначение VQ12 стенд для «союза» VQ1 и vq2; то есть, если VQ1 или vq2 является volatile, то VQ12 является volatile. Аналогично, пусть обозначение cq12 подставка для «соединения» cq1 и cq2; то есть, если CQ1 или cq2 является const, то cq12 является const. Если E2 заявлен как изменяемый элемент , то тип E1.E2 является «vq12T». Если E2 не объявлен изменяемый элемент, а затем тип E1.E2 является «cq12 VQ12T».

VQ1 является volatile и vq2 пуст. Таким образом, vq12 является volatile. Таким образом, тип выражения равен volatile T, который равен lThreadInfo* volatile.

Смежные вопросы