2015-02-09 2 views
0

Хорошо, я понимаю, что предупреждение GCC 4.x «разыменованный тип указателя разыгрывает нарушающие правила строгого сглаживания» - это не шутка, и я должен очистить свой код ,Тип-punning (GCC) - приращение указателя в стеке

У меня есть код, который компилируется и работает отлично с GCC 3.x, и был бы очень рад, если бы он сделал это с GCC 4.x. Предположим, я хочу, чтобы собранный код был как можно короче: функция получает переданный указатель и должна записывать там некоторые данные. Мой исходный код использует указатель непосредственно в стеке (без копии) и увеличивает его (обратите внимание, что я не хочу передавать инкрементное значение обратно вызывающему абоненту). Вы можете также думать о передаче параметров по регистру - тогда любая копия будет накладными.

Так что это был мой «идеальный» код:

void foo(void *pdataout) { 
    for (int i=16; i--;) 
     *(*reinterpret_cast<BYTE**>(&pdataout))++ = 255; 
} 

Я попробовал тот или иной вариант (обратите внимание, что адрес-оператор должен быть применен к «pdataout» перед любым типом литьем):

void foo(void *pdataout) { 
    BYTE *pdo = reinterpret_cast<BYTE*>(*reinterpret_cast<BYTE**>(&pdataout)); 

    for (int i=16; i--;) 
     *pdo++ = 255; 
} 

, а также это:

void foo(void *pdataout) { 
    BYTE *pdo = *reinterpret_cast<BYTE**>(&pdataout); 

    for (int i=16; i--;) 
     *pdo++ = 255; 
} 

Ничто не радует GCC 4.x ... Это последнее один делает - но она использует копию параметра ш мне это не нравится. Есть ли способ сделать это без копии? Я понятия не имею, как сказать это компилятор :-(

void foo(void *pdataout) { 
    BYTE *pdo = reinterpret_cast<BYTE*>(pdataout); 

    for (int i=16; i--;) 
     *pdo++ = 255; 
} 
+0

Я действительно не понимаю, почему копирование указателя (и увеличение только копии) может решить любую проблему - или код еще опасен, но GCC его не обнаруживает? Сравните сначала с последним фрагментом кода. Я был бы рад, если кто-нибудь сможет объяснить! – tueftl

+0

Кажется, проблема может быть упрощена до 'float test = 0.0f; если (! * (Длинный *) & тест) {}; long * ptest = (long *) &test; if (! * Ptest) {}; ': первая строка' & test' вызывает предупреждение, другие - нет. Зачем? И последние 2 строки безопасны? – tueftl

ответ

0

Насколько я теперь понимаю, несмотря на то, больше нет предупреждения по НКУ, используя окольные с помощью дополнительной переменной не безопасно!

Для меня (как union не используется) единственное реальное решение - использовать компилятор -fno-strict-aliasing. Только с этим GCC знает, что указатели разного типа на один и тот же адрес памяти могут ссылаться на одну и ту же переменную.

This article, наконец, помог мне вернуться строгое сглаживание.