这段代码:
class X {
int member;
};
volatile X a;
X b = a;
Run Code Online (Sandbox Code Playgroud)
失败并出现错误:
prog.cpp:6:7: error: no matching function for call to ‘X::X(volatile X&)’
prog.cpp:6:7: note: candidates are:
prog.cpp:1:7: note: X::X()
prog.cpp:1:7: note: candidate expects 0 arguments, 1 provided
prog.cpp:1:7: note: X::X(const X&)
prog.cpp:1:7: note: no known conversion for argument 1 from ‘volatile X’ to ‘const X&’
Run Code Online (Sandbox Code Playgroud)
有什么办法可以让编译器为我生成易失性复制构造函数吗?
该声明:
volatile unsigned char * volatile p = (volatile unsigned char * volatile)v;
Run Code Online (Sandbox Code Playgroud)
在MSVC v14.1中生成警告C4197:
警告C4197:'volatile unsigned char*volatile':忽略强制转换中的顶级volatile
2011 C标准([N1570] 6.7.3 4.)规定:"与限定类型相关联的属性仅对表达式有意义,即l值",因此此投射中的顶级volatile将被忽略并生成这个警告.
该代码的作者指出,它不违反C标准,并且需要阻止一些GCC优化.他通过以下代码说明了代码的问题:https://godbolt.org/g/xP4eGz
#include <stddef.h>
static void memset_s(void * v, size_t n) {
volatile unsigned char * p = (volatile unsigned char *)v;
for(size_t i = 0; i < n; ++i) {
p[i] = 0;
}
}
void f1() {
unsigned char x[4];
memset_s(x, sizeof x);
}
static void memset_s_volatile_pnt(void * v, size_t n) {
volatile unsigned …Run Code Online (Sandbox Code Playgroud) 我想使用易失性位字段结构来设置硬件寄存器,如以下代码
union foo {
uint32_t value;
struct {
uint32_t x : 1;
uint32_t y : 3;
uint32_t z : 28;
};
};
union foo f = {0};
int main()
{
volatile union foo *f_ptr = &f;
//union foo tmp;
*f_ptr = (union foo) {
.x = 1,
.y = 7,
.z = 10,
};
//*f_ptr = tmp;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,编译器会将其多次写入STR、LDR HW 寄存器。可怕的是,当寄存器被写入时,它会立即触发硬件工作。
main:
@ args = 0, pretend = 0, frame = 0
@ frame_needed …Run Code Online (Sandbox Code Playgroud) 我有一个小类,它使用std :: atomic进行无锁操作。由于该课程被广泛调用,因此影响了性能,并且遇到了麻烦。
该类类似于LIFO,但是一旦调用pop()函数,它仅返回其环形缓冲区的最后写入元素(仅当自上次pop()之后存在新元素时)。
一个线程正在调用push(),另一个线程正在调用pop()。
由于这占用了我的计算机时间太多,因此我决定进一步研究std :: atomic类及其memory_order。我已经阅读了很多StackOverflow以及其他来源和书籍中的memory_order帖子,但是我无法对不同的模式有一个清晰的了解。特别是,我在获取和释放模式之间挣扎:我也看不出为什么它们与memory_order_seq_cst不同。
memory_order_relaxed:在同一线程中,原子操作是即时的,但是其他线程可能无法立即看到最新的值,它们将需要一些时间才能被更新。编译器或OS可以自由地对代码进行重新排序。
memory_order_acquire / release:由atomic :: load使用。它防止重新排序之前存在的代码行(编译器/ OS可能在此行之后对其重新排序),并使用此线程或另一个线程中的memory_order_release或memory_order_seq_cst读取存储在此原子上的最新值。memory_order_release还可以防止对该代码重新排序之后的代码。因此,在获取/发布中,两者之间的所有代码都可以被OS改组。我不确定这是在同一线程还是不同线程之间。
memory_order_seq_cst:最容易使用,因为就像我们使用变量的自然写法一样,立即刷新其他线程加载函数的值。
template<typename T>
class LockFreeEx
{
public:
void push(const T& element)
{
const int wPos = m_position.load(std::memory_order_seq_cst);
const int nextPos = getNextPos(wPos);
m_buffer[nextPos] = element;
m_position.store(nextPos, std::memory_order_seq_cst);
}
const bool pop(T& returnedElement)
{
const int wPos = m_position.exchange(-1, std::memory_order_seq_cst);
if (wPos != -1)
{
returnedElement = m_buffer[wPos]; …Run Code Online (Sandbox Code Playgroud)