Здравствуйте, nazavrik, Вы писали:
N>Здравствуйте, uzhas, Вы писали:
U>>Здравствуйте, nazavrik, Вы писали:
N>>>В общем случае все прекрасно работает. Но что-то сомневаюсь посчет безопасности такого кода. U>>Работы с сырыми указателями — это всегда опасно U>>Вот такой вариант чуток безопаснее =) U>>
Здравствуйте, nazavrik, Вы писали:
N>В общем случае все прекрасно работает. Но что-то сомневаюсь посчет безопасности такого кода.
С вычитанием никаких проблем. А вот с условием цикла — есть проблема. Если в строке не будет точки, указатель уйдет за границы строки. Надо добавить проверку на конец строки.
Здравствуйте, nazavrik, Вы писали:
N>В общем случае все прекрасно работает. Но что-то сомневаюсь посчет безопасности такого кода.
Работы с сырыми указателями — это всегда опасно
Вот такой вариант чуток безопаснее =)
ладно, конкретно с доменными именами мимо, но я хотел обратить внимание ТС на разные кодировки символов в строке и что для этих целех есть более правильные стредства, чем арифметика над указателями
Здравствуйте, nazavrik, Вы писали:
N>Добрый день!
N>Вопрос: насколько безопасно использовать вычитание указателей (на начало и конец) для определения длины строки?
N>У меня есть доменное имя: domainname.com. Мне нужно выделить название хоста: domainname. Я делаю следующее:
N>
N>В общем случае все прекрасно работает. Но что-то сомневаюсь посчет безопасности такого кода.
Насчет арифм. операций с указателями — неплохо описано у K&R "C programming language". Неопределены результаты операций (вт.ч. сравнения "больше-меньше") для указателей, принадлежащих разным массивам. Указатели на элементы в одном и том же массиве можно сравнивать и вычитать, если я ничего не путаю.
P.S. C-Строки не фрагментируются и всегда лежат в памяти "одним куском".
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Здравствуйте, nazavrik, Вы писали:
N>А не может в результате специфики чего-нибудь логически цельная строка физически располагаться в разных частях памяти (как при динамической работе с памятью), что исказит значение длины?
Не может. Это просто массив. Даже если память выделяется динамически — либо выделится сплошной кусок необходимого размера, либо не выделится ничего.
Здравствуйте, nazavrik, Вы писали:
N>А не может в результате специфики чего-нибудь логически цельная строка физически располагаться в разных частях памяти (как при динамической работе с памятью), что исказит значение длины?
Проблемы такого характера противоречат стандарту языка.
выражение "domainname.com" имеет тип char[15], а для массивов зафиксировано, что все его элементы лежат последовательно в памяти
8.3.4 Arrays
1.
<skip>
An object of array type contains a contiguously allocated nonempty set of N sub-objects of type T
Функция abs вам тоже не нужна, ибо
5.7 Additive operators
<skip>
6.
When two pointers to elements of the same array object are subtracted, the result is the difference of the
subscripts of the two array elements. The type of the result is an implementation-defined signed integral
type; this type shall be the same type that is defined as ptrdiff_t in the <cstddef> header (18.1). As
with any other arithmetic overflow, if the result does not fit in the space provided, the behavior is undefined.
In other words, if the expressions P and Q point to, respectively, the i-th and j-th elements of an
array object, the expression (P)-(Q) has the value i–j provided the value fits in an object of type
ptrdiff_t. Moreover, if the expression P points either to an element of an array object or one past the
last element of an array object, and the expression Q points to the last element of the same array object, the
expression ((Q)+1)-(P) has the same value as ((Q)-(P))+1 and as -((P)-((Q)+1)), and has
the value zero if the expression P points one past the last element of the array object, even though the
expression (Q)+1 does not point to an element of the array object. Unless both pointers point to elements
of the same array object, or one past the last element of the array object, the behavior is undefined.
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, nazavrik, Вы писали:
N>>В общем случае все прекрасно работает. Но что-то сомневаюсь посчет безопасности такого кода. U>Работы с сырыми указателями — это всегда опасно U>Вот такой вариант чуток безопаснее =) U>
Здравствуйте, _stun_, Вы писали:
__>И что, его можно инкрементировать до бесконечности?
Ну мы же размер объекта в памяти и змеряем, а не до бесконечности инкрементируем...
__>Про abs — не ко мне. А в остальном — откуда вообще уверенность, что этот указатель не указывает на мусор где-нибудь ближе к концу адресного пространства?
Ну и что? Как это к знаку разности относится? Будет либо UB, либо, если на платформе можно размещать объекты, пересекая границу адресного пространства, будет вообще корректная работа...
E>>3) Указатель переполнится не может, он вообще не число, для него это понятие нерелевантно... __>Надо еще понятие арифметики указателей тогда на что-нибудь другое заменить
Ну если указатель выйдет за пределы массива, то начнётся UB...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, LuciferSaratov, Вы писали:
LS>Здравствуйте, nazavrik, Вы писали:
N>>В общем случае все прекрасно работает. Но что-то сомневаюсь посчет безопасности такого кода.
LS>С вычитанием никаких проблем. А вот с условием цикла — есть проблема. Если в строке не будет точки, указатель уйдет за границы строки. Надо добавить проверку на конец строки.
Да, это понятно, обработка доменного имени значительно сложнее (ресурсная часть, параметры и пр. в общем случае тоже обрабатываются). Здесь все максимально упрощено для разъяснения данного вопроса.
А не может в результате специфики чего-нибудь логически цельная строка физически располагаться в разных частях памяти (как при динамической работе с памятью), что исказит значение длины?
Здравствуйте, nazavrik, Вы писали:
N>А не может в результате специфики чего-нибудь логически цельная строка физически располагаться в разных частях памяти (как при динамической работе с памятью), что исказит значение длины?
Думаю, такого быть не может. Я стандарт не процитирую, но подобное сломало бы всю адресную арифметику.
Здравствуйте, LuciferSaratov, Вы писали:
LS>Здравствуйте, nazavrik, Вы писали:
N>>А не может в результате специфики чего-нибудь логически цельная строка физически располагаться в разных частях памяти (как при динамической работе с памятью), что исказит значение длины?
LS>Думаю, такого быть не может. Я стандарт не процитирую, но подобное сломало бы всю адресную арифметику.
Здравствуйте, LuciferSaratov, Вы писали:
N>>А не может в результате специфики чего-нибудь логически цельная строка физически располагаться в разных частях памяти (как при динамической работе с памятью), что исказит значение длины? LS>Думаю, такого быть не может. Я стандарт не процитирую, но подобное сломало бы всю адресную арифметику.
Логическая цельность — вещь тонкая.
Если мы говорим о сишных строках, — они всегда занимают последовательные участки адресного пространства.
Правда, при сегментной модели памяти может дополнительно возникать неоднозначность адресов — когда один и тот же физический адрес кодируется двумя разными парами селектор:смещение. Но кто нам мешает ввести "основную" и "прочие" нумерации, то есть плоскую модель плюс сегментные нахлобучки поверх неё.
Такая проблема возникала для 16-битного режима 8086, поскольку каждый сегмент охватывал только 64К, и сегменты наслаивались друг на друга с шагом в 16 байтов.
Это всего лишь усложняло адресную арифметику. Поэтому вводились 32-битные дешёвые неоднозначные large и дорогие однозначные huge указатели (устроенные одинаково — 16:16, но с пофигистичной или строгой арифметикой).
Если же цельная строка, к примеру, находится в файле, и мы проецируем смежные участки файла в память — то нельзя поручиться, что эти проекции окажутся в смежных участках адресного пространства. Но внутри проекции непрерывность, естественно, сохранится (иначе нафиг такая проекция нужна).
Или если цельная строка засунута в std::deque<char> или вообще std::list<char>. Логически, это строка, а физически — россыпь.
__>>Ну и проверить минимум на неотрицательность.
N>Отрицательность, если имеет место, убирается функцией abs(). Спасибо!
Ничего не понимаю. Как это можно, выполняя ptr++ несколько раз, получить меньше, чем исходное значение ? Вы что, через системное пространство прошли и опять с нуля начали ?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Ничего не понимаю. Как это можно, выполняя ptr++ несколько раз, получить меньше, чем исходное значение ? Вы что, через системное пространство прошли и опять с нуля начали ?
Мир не ограничивается Windows. Да, указатель тоже может переполниться, и далеко не всегда при этом операционная система как-то отреагирует сама. Довольно часто и системы никакой нет. И системного пространства тоже
Здравствуйте, _stun_, Вы писали:
__>Мир не ограничивается Windows. Да, указатель тоже может переполниться, и далеко не всегда при этом операционная система как-то отреагирует сама.
Операционная система реагировать на то, что некое целое переполнилось, никак не будет, потому как не обязана.
>Довольно часто и системы никакой нет. И системного пространства тоже
Здравствуйте, _stun_, Вы писали:
__>Мир не ограничивается Windows. Да, указатель тоже может переполниться, и далеко не всегда при этом операционная система как-то отреагирует сама. Довольно часто и системы никакой нет. И системного пространства тоже
1) В size_t должен влезать размер любого объекта в памяти.
2) В любом случае не ясно, если даже длина строчки не помещается в выбранный целочисленный тип, чем тут поможет abs...
3) Указатель переполнится не может, он вообще не число, для него это понятие нерелевантно...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, x905, Вы писали:
X>изучи регулярные выражения — как раз для твоего случая, да и вообще пригодится X>т.к. сейчас ввели домены на других языках, то твой код неверен
Почему не верен? Верен и как раз IDN проверяются и конвертируются тоже. Принципиальная разница между традиционным и доменным именем — это наличие префикса "xn--", а так все то же самое.
Здравствуйте, nazavrik, Вы писали:
N>Здравствуйте, x905, Вы писали:
X>>изучи регулярные выражения — как раз для твоего случая, да и вообще пригодится X>>т.к. сейчас ввели домены на других языках, то твой код неверен
N>Почему не верен? Верен и как раз IDN проверяются и конвертируются тоже. Принципиальная разница между традиционным и доменным именем — это наличие префикса "xn--", а так все то же самое.
ТС ползает по строке и считает символы, если жи строка будет в UTF8, то размер символа != 1 байт
пора бы уже прекратить пользоваться char* для строк, есть же множество удобный и безопасных средств, например qstring
Здравствуйте, x905, Вы писали:
N>>Почему не верен? Верен и как раз IDN проверяются и конвертируются тоже. Принципиальная разница между традиционным и доменным именем — это наличие префикса "xn--", а так все то же самое.
X>ТС ползает по строке и считает символы, если жи строка будет в UTF8, то размер символа != 1 байт
как размер юникодного символа влияет на корректность алгоритма нахождения доменного имени в строке?
Здравствуйте, x905, Вы писали:
X>Здравствуйте, nazavrik, Вы писали:
N>>Здравствуйте, x905, Вы писали:
X>>>изучи регулярные выражения — как раз для твоего случая, да и вообще пригодится X>>>т.к. сейчас ввели домены на других языках, то твой код неверен
N>>Почему не верен? Верен и как раз IDN проверяются и конвертируются тоже. Принципиальная разница между традиционным и доменным именем — это наличие префикса "xn--", а так все то же самое.
X>ТС ползает по строке и считает символы, если жи строка будет в UTF8, то размер символа != 1 байт X>пора бы уже прекратить пользоваться char* для строк, есть же множество удобный и безопасных средств, например qstring
Для представления IDN используются все те же двадцать с лишним латинских символов, которые в кодировке UTF8 будут представлены 1 байтом. Нет? А если нужно будет иметь дело с национальными алфавитами, то там да, необходимо предусмотреть отдельную обработку.
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, _stun_, Вы писали:
E>1) В size_t должен влезать размер любого объекта в памяти.
И что, его можно инкрементировать до бесконечности?
E>2) В любом случае не ясно, если даже длина строчки не помещается в выбранный целочисленный тип, чем тут поможет abs...
Про abs — не ко мне. А в остальном — откуда вообще уверенность, что этот указатель не указывает на мусор где-нибудь ближе к концу адресного пространства?
E>3) Указатель переполнится не может, он вообще не число, для него это понятие нерелевантно...
Надо еще понятие арифметики указателей тогда на что-нибудь другое заменить
Будет UB, кто же спорит? И что, UB — не повод принять разумные меры предосторожности? Ну, хотя бы сообщить о том, что оно имеет место, если система на него начихала?
Здравствуйте, _stun_, Вы писали:
__>Будет UB, кто же спорит? И что, UB — не повод принять разумные меры предосторожности? Ну, хотя бы сообщить о том, что оно имеет место, если система на него начихала?
Если ты про assert, то я согласен, что он в тему, хотя и не согласен, что обязателен.
А если ты про abs, то он точно не в тему и является ошибкой...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, nazavrik, Вы писали:
N>Добрый день!
N>Вопрос: насколько безопасно использовать вычитание указателей (на начало и конец) для определения длины строки?
N>У меня есть доменное имя: domainname.com. Мне нужно выделить название хоста: domainname. Я делаю следующее:
N>
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, LuciferSaratov, Вы писали:
N>>>А не может в результате специфики чего-нибудь логически цельная строка физически располагаться в разных частях памяти (как при динамической работе с памятью), что исказит значение длины? LS>>Думаю, такого быть не может. Я стандарт не процитирую, но подобное сломало бы всю адресную арифметику.
К>Логическая цельность — вещь тонкая.
К>Если мы говорим о сишных строках, — они всегда занимают последовательные участки адресного пространства. К>Правда, при сегментной модели памяти может дополнительно возникать неоднозначность адресов — когда один и тот же физический адрес кодируется двумя разными парами селектор:смещение. Но кто нам мешает ввести "основную" и "прочие" нумерации, то есть плоскую модель плюс сегментные нахлобучки поверх неё. К>Такая проблема возникала для 16-битного режима 8086, поскольку каждый сегмент охватывал только 64К, и сегменты наслаивались друг на друга с шагом в 16 байтов. К>Это всего лишь усложняло адресную арифметику. Поэтому вводились 32-битные дешёвые неоднозначные large и дорогие однозначные huge указатели (устроенные одинаково — 16:16, но с пофигистичной или строгой арифметикой).
Насколько я припоминаю те стародавние времена, разница между large и huge указателями немного в другом — массив, на который указывает large указатель, обязан целиком умещаться в одном сегменте, а массив, на который указывает huge может занимать больше одного сегмента (соответственно при инкременте/декременте указателя проверяется переход через границу сегмента). По идее та же фигня должна происходить и при вычитании указателей... Я не прав?
К>Если же цельная строка, к примеру, находится в файле, и мы проецируем смежные участки файла в память — то нельзя поручиться, что эти проекции окажутся в смежных участках адресного пространства. Но внутри проекции непрерывность, естественно, сохранится (иначе нафиг такая проекция нужна).
К>Или если цельная строка засунута в std::deque<char> или вообще std::list<char>. Логически, это строка, а физически — россыпь.
Тогда уже и тупой инкремент указателя при поиске символа строки нифига не прокатит. И вообще тогда мы уже будем работать не с указателями, а с итераторами, ибо с указателями получится бред. А в "итераторной арифметике" такая операция предусмотрена, называется distance(_First, _Last). Странно, что ты о ней не упомянул... Правда, там уже начинается свистопляска со сложностью вычислений. Ну, собственно, если у тебя std::list<char> — чего же хотеть? Или я что-то путаю?
Здравствуйте, programmater, Вы писали:
P>Насколько я припоминаю те стародавние времена, разница между large и huge указателями немного в другом — массив, на который указывает large указатель, обязан целиком умещаться в одном сегменте, а массив, на который указывает huge может занимать больше одного сегмента (соответственно при инкременте/декременте указателя проверяется переход через границу сегмента). По идее та же фигня должна происходить и при вычитании указателей... Я не прав?
Не "немного в другом", а и в этом тоже.
Во-первых, сравнение huge-указателей однозначно (мысленно приводим их к 20-битному абсолютному виду), а large — unspecified (хочешь сравнивать указатели из разных доменов — ССЗБ; а указатели с разными сегментами — заведомо принадлежат разным доменам).
Во-вторых, арифметика — при перескоке через границу сегмента либо определена, либо undefined (или unspecified? но всё равно мало приятного).
К>>Если же цельная строка, к примеру, находится в файле, и мы проецируем смежные участки файла в память — то нельзя поручиться, что эти проекции окажутся в смежных участках адресного пространства. Но внутри проекции непрерывность, естественно, сохранится (иначе нафиг такая проекция нужна). К>>Или если цельная строка засунута в std::deque<char> или вообще std::list<char>. Логически, это строка, а физически — россыпь.
P>Тогда уже и тупой инкремент указателя при поиске символа строки нифига не прокатит. И вообще тогда мы уже будем работать не с указателями, а с итераторами, ибо с указателями получится бред. А в "итераторной арифметике" такая операция предусмотрена, называется distance(_First, _Last). Странно, что ты о ней не упомянул... Правда, там уже начинается свистопляска со сложностью вычислений. Ну, собственно, если у тебя std::list<char> — чего же хотеть? Или я что-то путаю?
Это я показывал, что логическая цельность не обязательно ведёт к физической цельности.
Например, текстовые редакторы не держат весь документ в монолитном куске памяти.
А уж итераторы-шмитераторы, маппинг-шмаппинг — это нюансы.