2014-10-02 2 views
4

Я работаю над встроенной целью и хочу определить пулы памяти.Как применить маску к адресу const void *?

Адрес памяти представлен как void*. Однако в конкретном случае эти адреса кэшируются, и я хочу, чтобы они не смогли их напрямую получить «реальный» аппаратный адрес.

Я хочу, чтобы определить адрес начала memory_area (который является только маркером):

#define UNCACHE_MASK 0xABCDEF12UL // Value of the mask to apply 
extern uint32_t memory_area; // Global, defined somewhere else 
const void * virtual_address = &memory_area; // OK 
const void * real_address = 
    (void*)(virtual_address | UNCACHE_MASK); // guilty line 

К сожалению, GCC не позволит мне сделать это:

error: invalid operands to binary | (have 'const void *' and 'long unsigned int') 

В отчаянии Я пробовал:

const void * real_address = 
    (void*)(((uint32_t)virtual_address) | UNCACHE_MASK); // guilty line 

напрасно:

error: initializer element is not constant 

Я действительно хочу сохранить const для безопасности: это достижимо?

[EDIT]

  • Я использую gcc v4.9 (с -std=gnu99 и много -Wxxx флагов) на Linux.
  • Отрывок из файла .h, переменные являются «глобальными».
+2

Здесь, вероятно, не имеет значения, вы знаете, что ваша арка 32-разрядная, но обычно вы должны использовать 'uintptr_t' для указания указателей на целые числа. (потому что в тот день, когда вы переносите свой материал на 64 бит, вы пожалеете об этом :) –

+0

Правильно, спасибо за подсказку! – Coconop

+0

Я не думаю, что «кеш» означает то, что вы думаете о нем, здесь. Звучит так, будто вы говорите о * виртуальных адресах *, которые не являются концепцией кэширования. Кэширование не изменяет адреса. – unwind

ответ

2

Вы можете назначить это, используя выражение побитового ИЛИ внутри функции. Вы не можете выполнить инициализацию в глобальной области действия, как вы показали, потому что действительно значение не известно компилятору (возможно, на C++, но не на C). Если вы добавите броски и переместите назначение внутри области функций, оно будет работать.

Когда вы говорите, это:

const void * real_address 

Это означает, что «real_address является указателем на постоянной памяти неизвестного типа.» Если вы хотите, чтобы указатель также не может быть изменяемым (в дополнение к тому, что он указывает на), вы можете сделать это:

const void * const real_address 

Но тогда вы не сможете инициализировать его внутри функции, как вам нужно делать. Я полагаю, вы могли бы отбросить константу внутри функции, но это может быть даже не законным в C.

+1

Невозможно присвоить значение функции 'real_address' в функции, если вы определяете его' void const * const'. – user694733

+0

@ user694733: спасибо, я исправил свой ответ, чтобы отразить это. –

+0

Я, наконец, решил отказаться от 'const', просто объявить его глобальным и задать адрес внутри функции. – Coconop

5

Просто определите. Это не может быть случайно изменено.

#define real_address ((void*)((uint32_t)virtual_address | UNCACHE_MASK)) 

Дополнительная инструкция или два за использование не очень дорого.

Также добавьте ключевое слово const в переменную virtual_address, поэтому ее нельзя изменить.

const void* const virtual_address = ... 
+0

Хороший совет, он фактически решает проблему в моем фрагменте кода, однако я ищу оптимизацию, а 'real_address' используется в других местах для других вычислений, и я хочу избежать этих дополнительных инструкций. – Coconop

+1

Если это перерасчет действительно является узким местом (я сомневаюсь), вы можете попытаться сохранить значение один раз в начале в переменной. Если вы часто используете эту переменную, она всегда должна быть горячей в кеше и не приносить много лишних затрат при перезагрузке. –

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