Кастинг в C - PullRequest
       127

Кастинг в C

1 голос
/ 29 марта 2019

В настоящее время я пытаюсь избежать арифметических операций с указателями в C для написания эмулятора.

Обычно, если вы добавляете 1 к указателю в C, вы добавляете размер указателя на объектвместо.Однако я пытаюсь работать с битами и байтами, так что это нежелательно.

Мне было интересно, использовал ли я слишком много скобок в этом примере:

*(int16_t *)(((intptr_t)bc)+sp)

А если нет,тогда это эквивалентно этому?:

*(int16_t *)((intptr_t)bc+sp)

sp - это адрес стека с выравниванием по страницам для моего эмулятора (получен через. mmap без установки MAP_FIXED).Это тип intptr_t.

bc - это имя типа int16_t *.Это указатель на комбинацию из двух int8_t.

Ответы [ 2 ]

2 голосов
/ 29 марта 2019

(((intptr_t)bc)+sp) эквивалентно t ((intptr_t)bc+sp).


Но весь этот подход "избегать арифметики указателей" не переносим.

Как минимум 3 проблемы:

  • Указатели, преобразованные в целое число, не всегда поддерживают необходимые математические свойства.

    // possible outcome
    uint16_t x[2];
    printf("%llx\n", (unsigned long long) (intptr_t) &x[0]); // --> abcd0000
    printf("%llx\n", (unsigned long long) (intptr_t) &x[1]); // --> abcd0010
    

Разница в виде целых чисел может составлять 16, а не рассчитывать на 2 - даже если разница в 2 более распространена.

  • Далее, с *(int16_t *)((intptr_t)bc+sp), если sp нечетно, (int16_t *) может завершиться ошибкой из-за ограничений выравнивания.

  • Также возникают проблемы сглаживания. @ Эндрю Хенле

Такое избегание арифметики с указателями, хотя целые числа имеют различные ловушки - удачи.

2 голосов
/ 29 марта 2019

То, о чем вы спрашиваете, это приоритет оператора.Полный список можно найти здесь .

Операция '+' происходит после операции приведения типа.Следовательно, вам не нужен второй слой скобок, потому что приведение intptr_t применяется ПЕРВЫМ к bc, затем результат добавляется к sp.

...