Что такое на самом деле смещенный указатель?

#c #alignment

#c #выравнивание

Вопрос:

Смещенный указатель меня пугает. При разборе строки полезный метод, который я обычно использую, — это обработка группы символов как единого целого.

Так что, если я сравниваю строку, где <!— is 4 chars that mean begin comment, I would do…

 if( *(unsigned int*)string == tobe32('<!--') )
   // This is beggining of a comment possibly
  

Как вы можете видеть, я решаю проблему бесконечности. Но я все равно наткнусь на проблему с указателем выравнивания. Как будто я нахожусь в индексе 1 строки, приведет ли его к указателю unsigned int к получению 4-байтового объекта на границе в 1 байт?

Комментарии:

1. » Как вы можете видеть, я справляюсь с проблемой бесконечности» — это просто фикция…

Ответ №1:

Да, это почти наверняка будет смещенный указатель (a), приведение адреса на самом деле не должно изменять адрес, просто измените способ его обработки при разыменовании.

Однако это не обязательно проблема. Некоторые среды могут фактически вызвать аппаратное исключение, если вы сделаете это (некоторые ранние ARM, из памяти), некоторые будут работать немного медленнее (некоторые x86s), и, без сомнения, некоторым будет все равно. Так что это будет зависеть от вашей базовой среды.

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

Моим первым побуждением было бы просто написать встроенную функцию, которая проверяет четыре символа по отдельности, время и беспокоиться об оптимизации только в том случае, если есть реальная проблема. Это было бы что-то вроде:

 // Check first four characters match. Pre-condition is that both
// legacy-C-strings are at least four characters in length.

inline bool match4(const char *str, const char *match) {
    if (*str   != *match  ) return false;
    if (*str   != *match  ) return false;
    if (*str   != *match  ) return false;
    return *str == *match;
}
  

Это было бы моей отправной точкой, а не полагаться на, возможно, непереносимые решения с использованием литья.


(a) Если вы хотите узнать требования к выравниванию определенных типов, вы можете использовать alignof выражение C , например alignof(int) , предполагая, что у вас C 11 или лучше, и, действительно, у вас должно быть 🙂

Комментарии:

1. Спасибо за ваш любезный ответ. Моя проблема заключалась не в скорости, а в том, что техника упрощает ее. Но с этой проблемой выравнивания Cpp может оказаться не таким полезным языком, как я думал, и Java была права, полагаясь на копирование. Какова цель переосмысления приведения, если это небезопасно. Почему я только что узнал о смещении указателя; Хотя я никогда не испытывал его гнева?

2. Кроме того, tobe32 выдает значения времени компиляции вместо того, чтобы генерироваться во время выполнения.

3. @user13947194, мне было бы любопытно, почему вы считаете, что это проще. Мне кажется, что между выражением и небольшой разницей в простоте кодирования *(unsigned int*)string == tobe32('<!--') match4(string, "<!--") . И имейте в виду мой второй абзац. Это не обязательно проблема — если среды, на которые вы ориентируетесь, не заботятся о выравнивании, вам это тоже не нужно.

4. Имейте в виду, я не говорил о вашей функции match4. Это просто отлично. Я говорил о том, чтобы делать это как часть обычной итерации. Регулярная итерация, всплывающие символы, их проверка и соответствующие действия. Но я сопоставляю4 или просто stringLeftCompriseStringRight просто отлично.