(*(long *)((char **)(p) - 1))
Начинайте с указателем р. Передайте его типу (char **). Вычтите один из него. Передайте результат типу (long *), а затем разыщите результат. Другими словами, сдвиньте указатель на один байт и получите значение длинного, сохраненного на этом адресе. Эта операция может быть разбита на некоторых платформах, особенно в зависимости от типа p.
(*(int *)((int)(p) - 4))
Начать с указателя. Передайте его в int. Вычитание 4. Передайте его (int *) и разыщите результат. Теперь вместо обычной арифметики указателя вы прямо играете со значением указателя в виде целого числа, сдвигая его на четыре и читая int, на который указывает результат. Эта операция также будет нарушена в некоторых системах.
Думаю, мне удалось разобрать это, не заблудившись в парнах. В любом случае, не делайте этого. Это патологично. Там может быть какая-то странная встроенная задача разработки, где вы думаете, что что-то вроде этого - хорошая идея. Если это так, никогда не признавайте, что сделали это. Обвините его кому-нибудь, если он будет обнаружен.
Например, во втором примере, с р как INT *, а в системе с 8-битных символов и 32-битных целых чисел, вы в основном выполнения * (P-1)
OTOH, на машина с 16-битным int, вы делаете * (p-2), а на машине с 64-битным int вы делаете * (p-0.5), что неразумно, и может сильно сбой, а просто жаловаться о непринятом доступе к памяти. (И он заслуживает краха.) Используйте указатели, которые на самом деле указывают на правильный тип, и у вас никогда не должно быть причин делать такие глупости.
я бы * надежда * это на 32-битной машине. Этот код является 64-битным небезопасным. – 2010-12-16 05:48:24
Что такое `p`? [MoreCharactersToAppeaseJeffAtwood] – 2010-12-16 05:48:31