Когда я могу нарушить правила наложения имен? - PullRequest
4 голосов
/ 19 марта 2012

Я получил это предупреждение.Я хотел бы определенного поведения, но я хотел бы сохранить этот код как есть.Когда я могу нарушить правила псевдонимов?

предупреждение: разыменование указателя с типом-наказанием нарушит правила строгого псевдонима [-Wstrict-aliasing]

Строка - моя собственная строка, котораяэто стручокЭтот код вызывается из C. S может быть int.Строка в значительной степени struct String { RealString*s; }, но шаблонная и вспомогательная функции.Я делаю статическое утверждение, чтобы убедиться, что String является модулем, имеет размер 4 байта, а int равен 4 байта.Я также написал assert, который проверяет, все ли указатели> = NotAPtr.Это в моей новой / Malloc перегрузки.Я могу также включить это утверждение в строку, если вы предложите

Учитывая правила, которым я следую (в основном, строка является модулем и всегда имеет тот же размер, что и int), было бы хорошо, если бы я нарушил правила псевдонимов?Это один из немногих случаев, когда кто-то ломает его правильно?

void func(String s) {
    auto v=*(unsigned int*)&s;
    myassert(v);
    if(v < NotAPtr) {
        //v is an int
    }
    else{
        //v is a ptr
    }
}

Ответы [ 4 ]

4 голосов
/ 10 июня 2012

memcpy полностью поддерживается. То же самое относится к char* (например, вы можете использовать std::copy).

1 голос
/ 13 июля 2018

Стандарт определяет минимальный набор действий, который все соответствующие реализации должны обрабатывать предсказуемым образом, если только они не выходят за пределы трансляции (после чего все ставки отключены). Он не пытается определить все действия, которые должна поддерживать реализация, чтобы они подходили для какой-либо конкретной цели. Вместо этого поддержка действий, выходящих за рамки этих полномочий, рассматривается как проблема качества выполнения. Авторы признают, что реализация может соответствовать и при этом быть настолько плохого качества, что бесполезна.

Код, подобный вашему, должен использоваться для качественных реализаций, которые предназначены для низкоуровневого программирования и которые представляют вещи в памяти ожидаемым образом. Не следует ожидать, что его можно будет использовать в других видах реализаций, включая те, которые интерпретируют проблемы «качества реализации» как приглашение попытаться вести себя некачественно, но в соответствии с требованиями.

1 голос
/ 10 июня 2012

Если вы не можете изменить код на 2 функции в соответствии с предложением, почему бы и нет (требуется компилятор C99, который использует uintptr_t - для более старых MSVC вам нужно определить его самостоятельно, 2008/2010 должно быть в порядке):

void f(RealString *s) {
    uintptr_t int = reinterpret_cast<uintptr_t>(s);
    assert(int);
}
0 голосов
/ 19 марта 2012

Безопасный способ рассматривать переменную как два разных типа - это превращать ее в объединение. Одна часть объединения может быть вашим указателем, а другая - целым числом.

struct String
{
    union
    {
        RealString*s;
        int i;
    };
};
...