C ++ чистая арифметика указателей - PullRequest
1 голос
/ 08 марта 2012

Какой самый чистый способ выполнения арифметики с указателями в C ++? Я пытаюсь добавить n байт к адресу.

int *foo;
foo = static_cast<int*> (static_cast<unsigned int>(foo) + sizeof(T))

Позже вы можете переписать и использовать foo по-другому

char* somestr = reinterpret_cast<char*>(foo)

Это достаточно хорошо? Теперь я понимаю, что реализация указателей не гарантирует, что все указатели (char*, int*) будут реализованы одинакового размера. Поэтому не уверен, что int* (должно быть foo*) и использование unsigned int для математики - самое чистое решение. Кроме того, он должен работать как на 32, так и на 64 битах.

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

Ответы [ 2 ]

12 голосов
/ 08 марта 2012

Самый чистый способ выполнения арифметики с указателями - это не числа байтов, а строго типизированный. Не относитесь к массиву int как к чему-то другому, просто смещайте напрямую:

int* next = foo + n;

или

int* next = &foo[n];

Оба превосходят ваше решение для литья.

В тех случаях, когда вы работаете с байтовым буфером, используйте char*, а не (никогда!) int*. То есть

char* buffer = get_the_buffer();

// Pointer arithmetic uses sizeof(char) == 1

Если вам действительно нужно постепенно увеличивать байты внутри небайтового массива, сначала спросите себя, какого черта вы это делаете. Затем приведите к char* и сделайте арифметику указателя; делать не приведение к int или другие целочисленные типы:

char* foo_buffer = reinterpret_cast<char*>(foo);
char* whatever = foo_buffer + n;

Вместо char вы также можете использовать unsigned char, что, возможно, имеет больше смысла для представления байтов, но не влияет на арифметику указателей. Однако будьте осторожны с выравниванием: вы больше не можете надежно обращаться к увеличенному указателю, используя исходный тип. Это строго неопределенное поведение (= плохо !) Для доступа к невыровненной памяти. В лучших случаях это медленно. В худшем случае вылетает.

Само собой разумеется, что все это крайне низкий уровень. Такого кода больше почти нет. Даже низкоуровневые библиотеки должны предпочитать использовать стандартные библиотеки C ++ для такого рода кода, и в частности, арифметика указателей имеет все меньшее и меньшее использование.

1 голос
/ 08 марта 2012

Вы приводите указатель к типу int, что может привести к сбою, особенно если размер типа int отличается от размера типа указателя.

Если вы хотите сделать арифметику с указателями, используйте указатели:

foo = reinterpret_cast <int *> (reinterpret_cast <T *> (foo) + 1);

Обратите внимание на использование reinterpret_cast вместо static_cast.

Что еще более важно, это немного пахнет кодом - чего вы пытаетесь достичь здесь?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...