Назначить адрес памяти указателю - PullRequest
0 голосов
/ 10 декабря 2018

Я пытаюсь назначить адрес памяти указателю, но не могу его скомпилировать.Адрес является аппаратным регистром с отображением в памяти.

#include <memory>

template<void* Address>
struct ClassAImpl {
    uint64_t* Register = reinterpret_cast<uint64_t*>(Address);
};

uint8_t arrA[10] = { 1, 2, 3, 4 };
using ClassA1 = ClassAImpl<(void*)&arrA>;       // error: the address of the 'void' subobject of 'arrA' is not a valid template argument
using ClassA2 = ClassAImpl<0x8767876787678767>; // error: could not convert template argument '9756915996444559207' from 'long unsigned int' to 'void*'


template<uint64_t Address>
struct ClassBImpl {
    uint64_t* Register = reinterpret_cast<uint64_t*>(Address);
};

uint8_t arrB[10] = { 1, 2, 3, 4 };
using ClassB1 = ClassBImpl<(void*)&arrB>;       // error: conversion from 'void*' to 'long unsigned int' in a converted constant expression       
using ClassB2 = ClassBImpl<0x8767876787678767>; // This compiles.

Я хочу сделать ClassA1 из указателя на буфер и ClassA2 из фиксированного адреса.

Я компилирую C ++ с помощью Gcc8,2

Ответы [ 2 ]

0 голосов
/ 11 декабря 2018

Возможно, вы хотите что-то вроде:

#include <stdint.h>

uint64_t (&hw_regs)[10] = *reinterpret_cast<uint64_t(*)[10]>(0xdeadbeefUL);
uint64_t &hw_reg0 = hw_regs[0];

Сделайте ссылочные объекты volatile, если вам нужно.Если вы спрашиваете о правильном калибре пули для выстрела в ногу, вы знаете, что делаете.Раздел [expr.reinterpret.cast] Стандарта допускает это приведение, но, конечно, ссылка не является безопасной.

0 голосов
/ 11 декабря 2018

Я не знаю, что вы пытаетесь достичь, но вы попадаете в странное поведение параметров не типового шаблона.Нетипичный параметр шаблона не может быть создан с временными значениями.From https://en.cppreference.com/w/cpp/language/template_parameters:

"Для указателей на объекты аргументы шаблона должны указывать адрес полного объекта со статической продолжительностью хранения и связью (внутренней или внешней) или постоянным выражением, котороевычисляет соответствующий нулевой указатель или значение std :: nullptr_t. "

using ClassA1 = ClassAImpl<(void*)&arrA>; - temporary
using ClassA2 = ClassAImpl<0x8767876787678767>; - template argument is constant expression, template parameter is pointer to void, doesn't make any sense
using ClassB1 = ClassBImpl<(void*)&arrB>; - temporary
using ClassB2 = ClassBImpl<0x8767876787678767>; - constant expression which can be used as template parameter uint64_t
...