Аннотация:
Это первая часть, в которой обсуждаются «традиционные» строки в С. В С++ существуют более удобные механизмы для работы со строковыми данными, эти механизмы рассматриваются во второй части статьи. А зачем вообще обсуждать неудобные С-строки, если есть С++? К сожалению, совсем забыть о строках в стиле С нельзя по двум причинам:
1. существует большое библиотек (например, API операционных систем) работающих именно с С-строками
2. строковые классы в С++ все равно основаны на традиционных С-строках, и если мы хотим разобраться в том, как они работают, нам придется понимать их основы.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Ты неверно понимаешь, как "работают" многосимвольные литералы. Типом L'...' ПК>вне зависимости от количества символов остается wchar_t, равно как типом ПК>'...' — char.
типом '...' является char только в случает, если там в кавычках всего один символ, а если несколько — это уже int.
Здравствуйте, adontz, Вы писали:
A>А я что сказал? Есть версия где под символ отводится 2 байта и используются суррогаты, есть где 4. Или я не так прочёл топики?
Да нет, просто есть один, единый стандарт Уникод. Он определяет два набора символов: "узкий" UCS-2 и "широкий" UCS-4. Из них последний в себя первый включает. Логически текст составлен из последовательности симовлов и управляющих кодов. Физическое представление текста выполняется в соответствии с кодировками. Одна из них, та, которую мы обыкновенно подразумеваем, говоря "строки в Уникоде", — UTF-16.
UTF-16 определяет последовательности 16-битовых байтов, используемые для записи символов из набора символов UCS-4.
Есть еще другая кодировка, обычно так и называемая UCS-4, прямо отображающая все символы UCS-4 на 32-битовые байты.
Поэтому нельзя говорить о "двух версиях" Уникода. Можно говорить о двух различных кодировках, примерно так же, как мы говорим о кодировках ISO-8859-5 и Windows-1251.
Примечание. Слово "байт" здесь применено не в смысле байта языка Си и не в смысле байта аппаратуры.
> for (i=0;i<strlen(str);i++) {
> // работа со строкой, не изменяющая ее длину
> }
>
> str — это const char*. Компилятор сможет заменить вызовы strlen(str) > на константу?
const char* str или char* str — значения не имеет, т.к. в любой вызываемой
функции может быть сделан const_cast. Но если строка была создана
константной (т.е. это литерал или массив const char) и компилятору об этом
"известно" в точке использования, то он вполне имеет право "расчитывать" на то,
что попыток изменить строку не будет.
Если компилятор может наверняка "убедиться", что строка не изменяется и
содержимое строки или ее длина ему уже "известны", он вполне может заменить вызов стандартной функции strlen на соответствующее значение. Ничто
не запрещает компилятору использовать информацию о семантике стандартных функций
для оптимизации.
Более того, если транслятор "умеет" анализировать функции, определенные в разных
единицах трансляции, он вполне может делать подобные фокусы и с функциями,
определенными пользователем — во всяком случае стандарт ему этого не запрещает.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, LaFlour, Вы писали:
L> Чегото мельчают статьи — смылс написания данной статьи для меня остается L> загадкой.
Статьи разные нужны, статьи разные важны Так или иначе, РСДН посещает
значительное количество начинающих, которые высказываются за то, чтобы на РСДН
были статьи самого различного уровня. Эта статья, очевидно, ориентирована на
начинающих. Если она окажется кому-нибудь полезной — замечательно; если нет —
ничего страшного. Таким образом, в худшем случае данная статья может остаться
невостребованной. А в лучшем — поможет какому-нибудь новичку разобраться со
строками. Что же в этом плохого?
L> нет чтобы действительно чтото интересное написать чего нет в литературе L> или на русском не издавалось а про строки в любой книжке по C++ написано
Присылайте ваши работы по адресу: — мы с удовольствием
опубликуем их на сайте или — в зависимости от уровня статьи — в журнале
RSDN Magazine.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Сергей Аристов, Вы писали:
СА>Статья:
СА>Авторы: СА> Сергей Аристов
СА>Аннотация: СА>Это первая часть, в которой обсуждаются «традиционные» строки в С. В С++ существуют более удобные механизмы для работы со строковыми данными, эти механизмы рассматриваются во второй части статьи. А зачем вообще обсуждать неудобные С-строки, если есть С++? К сожалению, совсем забыть о строках в стиле С нельзя по двум причинам: СА>1. существует большое библиотек (например, API операционных систем) работающих именно с С-строками СА>2. строковые классы в С++ все равно основаны на традиционных С-строках, и если мы хотим разобраться в том, как они работают, нам придется понимать их основы.
Чегото мельчают статьи — смылс написания данной статьи для меня остается загадкой.
нет чтобы действительно чтото интересное написать чего нет в литературе или на русском не издавалось
а про строки в любой книжке по C++ написано
Здравствуйте, Аноним, Вы писали:
> Здравствуйте, dad, Вы писали: > LF>>>> Здравствуйте, Сергей Аристов, Вы писали: > СА>>>>> Статья: > А>>> В данном фрагменте А>>> for (i=0;i<strlen(str);i++) { А>>> // работа со строкой, не изменяющая ее длину А>>> } > А>>> str — это const char*. Компилятор сможет заменить вызовы strlen(str) А>>> на константу? > dad>> а на каком основании? > > Хотя srt и указатель, но все же const. Компилятор 1 раз вычисляет > strlen(str) и оптимизирует цикл, заменяя вызов strlen(str) на уже > вычисленную в общем-то константу?
Компилятор не имеет права делать предположений о функциональности strlen. Может, у нее побочные эффекты есть? Вызывать он ее должен каждый раз.
-- Всего хорошего!
-- Alex Alexandrov, e-mail: alex_alexandrov@fromru.com
Posted via RSDN NNTP Server 1.8 beta
It's kind of fun to do the impossible (Walt Disney)
dad>>>хотя, это очень интересно. т.е. на данный момент это усложняет программирование на c++ dad>>>так как делает написание портируемого кода очень трудоемким , но в перспективе , когда компиляторы "дорастут" до стандарта это делает язык очень мощным.
J>>как же оно усложнит портируемость, когда это касается в основном только оптимизации?
dad>я про тоже — отделение портируемости от оптимизации усложняет первое. если я пишу портируемый код я должен помнить об оптимизации и чем она "разноцветне" тем сложнее мне делать портиуремый код. или отказаться от оптимизации. когда "оптимизация" станет стандартизованной а не "незапрещенной", тогда будет значительнее круче , ведь так?
не совсем. На разных плаформах возможны разные оптимизации, и стандартизировать их не удастся. Достаточно уже inline.
А так — разные компиляторы, а тем более на разные платформы, генерят разный по качеству, скорости и размеру код, так что разница в методах оптимизации вообще роли не играет.
Программа ведь всегда будет работать, оптимизация — это просто фича сверху, но ни в коем случае не изменение семантики.
LF>Чегото мельчают статьи — смылс написания данной статьи для меня остается загадкой. LF>нет чтобы действительно чтото интересное написать чего нет в литературе или на русском не издавалось LF>а про строки в любой книжке по C++ написано
Просто вопросы в форуме частенько мелькали. Вот я и решил попробовать сделать предмет чуть понятнее для новичков.
A>#include <string.h>
A>int main (){
A> const char* s1="aaa";
A> const char* s2="aaaaaaaaaa";
A> int i1=strlen(s1);//i1=3
A> s1=s2;// :)
A> int i2=strlen(s1);//i2=10 :)
A>}
A>То есть на этапе компилляции вычислять strlen от const char * нельзя.
Отчего же? Компилятору вполне по силам установить, на какую строку будет ссылаться s1 по ходу исполнения данного участка кода...
A>Если бы A>const char* const s3="sdfdsfdsf"; A>то strlen(s3) могло бы быть заменено константой, хотя никто не гарантирует, что это будет правильным: A>кто-нибудь свободо применить const_cast и все испортить
А вот здесь уже у Стандарта все шито-крыто. При неконстантном доступе к объекту, изначально объявленному константным, (каковой доступ может быть произведен посредством а) явного const_cast и b) приведением типа строкового литерала) программа имеет неопределенное поведение. То есть, если все пойдет не так как надо, пеняйте на себя, все выкрутасы вы делаете на свой страх и риск.
Здравствуйте, Vamp, Вы писали:
V>>>Я хотел продемонстрировать, что С-строки важны, например, при работе с API. В С++ C-строки используются очень мало. A>>Это ясно. Просто удивило что на таком материале вдруг всплыло WinAPI. V>Общеизвестное внешнее API, распространенная функция из него, идеальная демонстрация строкового литерала. Полагаю, MacApi известно гораздо меньше.
В MacAPI тебе такое и не удастся проделать — там используются паскалевские строки, в которых в первом байте идет длина строки, и, соответственно, не нужен завершающий нуль, а получение длины строки сводится к простому чтению первого символа.
LF>Чегото мельчают статьи — смылс написания данной статьи для меня остается загадкой. LF>нет чтобы действительно чтото интересное написать чего нет в литературе или на русском не издавалось LF>а про строки в любой книжке по C++ написано
я тоже заметил какую моду сейчас на это. уже не первая статья про c++ строки попадается за последний месяц.
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Здравствуйте, LaFlour, Вы писали:
L> Чегото мельчают статьи — смылс написания данной статьи для меня остается L> загадкой. нет чтобы действительно чтото интересное написать чего нет в L> литературе или на русском не издавалось а про строки в любой книжке по L> C++ написано
Согласен. Предупреждение "Не забывайте пользоваться правильными функциями!" вообще философски звучит...
Не в обиду автору, но статья бесполезная. Если уж пытаешься дать введение в какую-то тему, надо хоть попытаться какую-то практическую задачу решить в качестве примера. А то получается — статья ради статьи...
-- Всего хорошего!
-- Alex Alexandrov, e-mail: alex_alexandrov@fromru.com
Posted via RSDN NNTP Server 1.8 beta
It's kind of fun to do the impossible (Walt Disney)
Re[2]: Строки в С и С++
От:
Аноним
Дата:
30.12.03 07:33
Оценка:
Здравствуйте, LaFlour, Вы писали:
LF>Здравствуйте, Сергей Аристов, Вы писали:
СА>>Статья:
В данном фрагменте
for (i=0;i<strlen(str);i++) {
// работа со строкой, не изменяющая ее длину
}
str — это const char*. Компилятор сможет заменить вызовы strlen(str) на константу?
LF>>Здравствуйте, Сергей Аристов, Вы писали:
СА>>>Статья:
А>В данном фрагменте А>for (i=0;i<strlen(str);i++) { А> // работа со строкой, не изменяющая ее длину А>}
А>str — это const char*. Компилятор сможет заменить вызовы strlen(str) на константу?
а на каком основании?
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Re[4]: Строки в С и С++
От:
Аноним
Дата:
30.12.03 07:56
Оценка:
Здравствуйте, dad, Вы писали:
LF>>>Здравствуйте, Сергей Аристов, Вы писали:
СА>>>>Статья:
А>>В данном фрагменте А>>for (i=0;i<strlen(str);i++) { А>> // работа со строкой, не изменяющая ее длину А>>}
А>>str — это const char*. Компилятор сможет заменить вызовы strlen(str) на константу?
dad>а на каком основании?
Хотя srt и указатель, но все же const. Компилятор 1 раз вычисляет strlen(str) и оптимизирует цикл, заменяя вызов
strlen(str) на уже вычисленную в общем-то константу?
По поводу достоинств и недостатков сишного подхода к хранению строк рекомендую посмотреть вот это. Все это, как обычно, обусловлено исторической необходимостью, а вовсе не целесообразностью. В частности:
Помните, как в C устроены строки: они представляют собой последовательность байтов, и последний байт всегда содержит особое значение 0. Это порождает два очевидных следствия:
1.. Единственый способ определить, где строка кончается (то есть узнать её длину) — это пройти по ней в поисках нулевого байта в самом конце.
2.. Строка не может содержать нулевые байты. Так что хранить произвольные двоичные данные вроде картинки в формате JPEG в строке нельзя.
Почему строки в языке C так работают? А потому что микропроцессор PDP-7, на котором разрабатывались UNIX и C, имел такой строковый тип ASCIZ. ASCIZ означало "ASCII с нулём (zero) на конце."
Неужели это единственный способ хранить строки? Конечно нет, более того, это наихудший способ хранить строки. Для всех нетривиальных программ, API, операционных систем, библиотек классов следует избегать использования ASCIZ строк, как чумы...
Хотя, это тоже субъектив...
-- Всего хорошего!
-- Alex Alexandrov, e-mail: alex_alexandrov@fromru.com
Posted via RSDN NNTP Server 1.8 beta
It's kind of fun to do the impossible (Walt Disney)
А>>>str — это const char*. Компилятор сможет заменить вызовы strlen(str) на константу?
dad>>а на каком основании?
А>Хотя srt и указатель, но все же const. Компилятор 1 раз вычисляет strlen(str) и оптимизирует цикл, заменяя вызов А>strlen(str) на уже вычисленную в общем-то константу?
весьма логично, но не понятно с чего бы это компилятору догадываться, что возвращаемое
значение зависит только от передаваемогьо значения?
другое дело — это требования к for стандартом — толи один раз вычисляется условие толи
каждую итерацию ?
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Re[6]: Строки в С и С++
От:
Аноним
Дата:
30.12.03 08:08
Оценка:
Здравствуйте, dad, Вы писали:
А>>>>str — это const char*. Компилятор сможет заменить вызовы strlen(str) на константу?
dad>>>а на каком основании?
А>>Хотя srt и указатель, но все же const. Компилятор 1 раз вычисляет strlen(str) и оптимизирует цикл, заменяя вызов А>>strlen(str) на уже вычисленную в общем-то константу?
dad>весьма логично, но не понятно с чего бы это компилятору догадываться, что возвращаемое dad>значение зависит только от передаваемогьо значения? dad>другое дело — это требования к for стандартом — толи один раз вычисляется условие толи dad>каждую итерацию ?
Имелась в виду именно strlen, а не какая-либо функция вообще.
_>По поводу достоинств и недостатков сишного подхода к хранению строк рекомендую посмотреть вот это. Все это, как обычно, обусловлено исторической необходимостью, а вовсе не целесообразностью. В частности:
_>
_>Хотя, это тоже субъектив...
стоинство сишного подхода что там можно и так и так делать можно нулевой байт под длину отводить можно отдельно хранить и т.дю. и т.п. разумеется придется отказаться от бибилиотечных фугкций.
кстати, не встречал бибилотеки ориентированной на паскалевские строки? в winapi например некоторые ункции требуют нулевой байт с диной строки. чудеса короче.
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Здравствуйте, dad, Вы писали:
А>>Хотя srt и указатель, но все же const. Компилятор 1 раз вычисляет strlen(str) и оптимизирует цикл, заменяя вызов А>>strlen(str) на уже вычисленную в общем-то константу?
dad>весьма логично, но не понятно с чего бы это компилятору догадываться, что возвращаемое dad>значение зависит только от передаваемогьо значения?
Ну это уже второй вопрос — как он догадается. Может быть он тока перед этим strlen компилировал, тогда он просто мог проставить флаг — результат этой функции зависит только от передаваемого значения. Другое дело, что большинство компиляторов такой оптимизацией не занимаются.
ты прямо как пророк каждый раз новые истины открываешь.
ПК>Если компилятор может наверняка "убедиться", что строка не изменяется и ПК>содержимое строки или ее длина ему уже "известны", он вполне может заменить вызов ПК>стандартной функции strlen на соответствующее значение. Ничто ПК>не запрещает компилятору использовать информацию о семантике стандартных функций ПК>для оптимизации.
Разве стандарты на библиотеку коррелируются со стандартами на язык вцелом?
Т.е. гипотетически можно разработать некую библиотеку "проллобировать" ее в комитете и ее семантика будет учитываться разработчиками компилятора?
таким образом стандартная бибилотке становится "частью" языка. т.е. функцию strlen можно рассматривать как языковую конмтрукцию, а не бибилотечную ?
ПК>Более того, если транслятор "умеет" анализировать функции, определенные в разных ПК>единицах трансляции, он вполне может делать подобные фокусы и с функциями, ПК>определенными пользователем — во всяком случае стандарт ему этого не запрещает.
а что он может "анализировать" ? например, если возвращаемая значение зависит от текущего времени ?
хотя, это очень интересно. т.е. на данный момент это усложняет программирование на c++
так как делает написание портируемого кода очень трудоемким , но в перспективе , когда компиляторы "дорастут" до стандарта это делает язык очень мощным.
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Здравствуйте, dad, Вы писали:
ПК>> Ничто не запрещает компилятору использовать информацию о семантике ПК>> стандартных функций для оптимизации.
d> Разве стандарты на библиотеку коррелируются со стандартами на язык вцелом?
Стандартные библиотеки C и C++ описываются в тех же самых документах,
что и сами языки.
d> Т.е. гипотетически можно разработать некую библиотеку "проллобировать" ее d> в комитете и ее семантика будет учитываться разработчиками компилятора?
Именно так. Необходимость реализации стандартных библиотек, фактически, всеми
разработчиками компиляторов является одним из факторов того, что "фичи" в них
включаются с особой осторожностью.
d> таким образом стандартная бибилотке становится "частью" языка. т.е. функцию d> strlen можно рассматривать как языковую конмтрукцию, а не бибилотечную ?
С некоторыми допущениями. В частности, взять адрес strlen можно.
ПК>> Более того, если транслятор "умеет" анализировать функции, определенные ПК>> в разных единицах трансляции, он вполне может делать подобные фокусы и ПК>> с функциями, определенными пользователем — во всяком случае стандарт ему ПК>> этого не запрещает.
d> а что он может "анализировать" ? например, если возвращаемая значение d> зависит от текущего времени ?
И это тоже. Например, если есть функция my_strlen, и компилятор "вывел"
в результате анализа, что ее возвращаемое значение зависит только от
передаваемых аргументов и что она не имеет побочных эффектов, то он вполне
может оптимизировать множественные вызовы данной функции.
d> хотя, это очень интересно. т.е. на данный момент это усложняет d> программирование на c++ так как делает написание портируемого кода очень d> трудоемким
Главное, что есть хоть какая-то спецификация на язык и стандартную библиотеку —
это делает написание переносимого кода намного более легким делом, чем когда
таких спецификаций нет.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, dad, Вы писали:
dad>таким образом стандартная бибилотке становится "частью" языка. т.е. функцию strlen можно рассматривать как языковую конмтрукцию, а не бибилотечную ?
Именно, и причем так и делается. Открой, к примеру файл cl.exe из MSVC++ 6 и разгляди его. Ты там много названий функций найдешь, прежде всего встроенные (intrinsic) функции: memcpy, strchr и т. д...
Конечно, компилятор знает семантику этих функций и, в принципе, имеет все возможности оптимизировать код с их применением.
Здравствуйте, dad, Вы писали:
dad>ты прямо как пророк каждый раз новые истины открываешь.
ПК>>Если компилятор может наверняка "убедиться", что строка не изменяется и ПК>>содержимое строки или ее длина ему уже "известны", он вполне может заменить вызов ПК>>стандартной функции strlen на соответствующее значение. Ничто ПК>>не запрещает компилятору использовать информацию о семантике стандартных функций ПК>>для оптимизации.
dad>Разве стандарты на библиотеку коррелируются со стандартами на язык вцелом?
Более того, они являются частью стандарта на язык.
dad>Т.е. гипотетически можно разработать некую библиотеку "проллобировать" ее в комитете и ее семантика будет учитываться разработчиками компилятора? dad>таким образом стандартная бибилотке становится "частью" языка. т.е. функцию strlen можно рассматривать как языковую конмтрукцию, а не бибилотечную ?
да, например, потоки cout и иже с ним гарантированно инициализируются до всех остальных.
но обычно все такие вещи касается оптимизации, а не семантики языка.
потом, поскольку функции стандартны, в стандарте описано, что им дозволяется делать, а что — нет, и компилятор вправе на это поведение рассчитывать, а реальзация библиотеки, занимающаяся чем-то нарушающим требования стандарта, не может уже считаться стандартной.
ПК>>Более того, если транслятор "умеет" анализировать функции, определенные в разных ПК>>единицах трансляции, он вполне может делать подобные фокусы и с функциями, ПК>>определенными пользователем — во всяком случае стандарт ему этого не запрещает.
dad>а что он может "анализировать" ? например, если возвращаемая значение зависит от текущего времени ?
что если он уверен, что функция не делает ничего страшного, он может забить на ее вызовы. Опять же это — лишь оптимизация, причем агрессивная, от которой легко можно избавиться при помощи volatile.
dad>хотя, это очень интересно. т.е. на данный момент это усложняет программирование на c++ dad>так как делает написание портируемого кода очень трудоемким , но в перспективе , когда компиляторы "дорастут" до стандарта это делает язык очень мощным.
как же оно усложнит портируемость, когда это касается в основном только оптимизации?
ПК>Именно так. Необходимость реализации стандартных библиотек, фактически, всеми ПК>разработчиками компиляторов является одним из факторов того, что "фичи" в них ПК>включаются с особой осторожностью.
таким образом резюме составленное вот так:
языки: c++
бибилотеки: stl
выдает человека (вроде меня) который не знает что такое c++
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
dad>>хотя, это очень интересно. т.е. на данный момент это усложняет программирование на c++ dad>>так как делает написание портируемого кода очень трудоемким , но в перспективе , когда компиляторы "дорастут" до стандарта это делает язык очень мощным.
J>как же оно усложнит портируемость, когда это касается в основном только оптимизации?
я про тоже — отделение портируемости от оптимизации усложняет первое. если я пишу портируемый код я должен помнить об оптимизации и чем она "разноцветне" тем сложнее мне делать портиуремый код. или отказаться от оптимизации. когда "оптимизация" станет стандартизованной а не "незапрещенной", тогда будет значительнее круче , ведь так?
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Здравствуйте, dad, Вы писали:
d> таким образом резюме составленное вот так: d> языки: c++ d> бибилотеки: stl d> выдает человека (вроде меня) который не знает что такое c++
Хм... Вопрос, конечно, интересный. Думаю, это сильно зависит от того, кто именно
будет оценивать такое резюме. Во всяком случае, лично мне было бы без разницы,
написал бы ты:
языки: c++
бибилотеки: stl
или так:
языки: c++ (в т.ч. stl)
Главное, что STL по твоим словам тебе известна. А решающим все равно были бы
анализ твоего кода, собеседование и т.п.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
>> Имелась в виду именно strlen, а не какая-либо функция вообще.
aa> А чего в ней есть такого неземного? Чем она отличается от прочего разнообразия функций?
Функция стандартной библиотеки C. Компилятор "знает" стандартную библиотеку и может проводить оптимизации недоступные для
пользовательких функций.
Кроме того strlen (как и некоторые другие функции стандартной библиотеки) имеет внутреннюю (intrinsic) форму, например для VC. Что
подтверждает ее "неземное" происхождение
J>не совсем. На разных плаформах возможны разные оптимизации, и стандартизировать их не удастся. Достаточно уже inline. J>А так — разные компиляторы, а тем более на разные платформы, генерят разный по качеству, скорости и размеру код, так что разница в методах оптимизации вообще роли не играет. Программа ведь всегда будет работать, оптимизация — это просто фича сверху, но ни в коем случае не изменение семантики.
а причем тут платформа?
если я пишу такой код
for ( i = 0 ; i < strlen(src) ...
я не уверен что он будет оптимизирован, если бы подобная оптимизация (хотябы стандартных функций) _строго_ регламентировалась стандартом было бы мощнее.
а если бы еще и та оптимизация о которйо упоминал Павел, то было бы еще мощнее.
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Здравствуйте, Сергей Аристов, Вы писали:
СА>Статья:
СА>Авторы: СА> Сергей Аристов
СА>Аннотация: СА>Это первая часть, в которой обсуждаются «традиционные» строки в С. В С++ существуют более удобные механизмы для работы со строковыми данными, эти механизмы рассматриваются во второй части статьи. А зачем вообще обсуждать неудобные С-строки, если есть С++? К сожалению, совсем забыть о строках в стиле С нельзя по двум причинам: СА>1. существует большое библиотек (например, API операционных систем) работающих именно с С-строками СА>2. строковые классы в С++ все равно основаны на традиционных С-строках, и если мы хотим разобраться в том, как они работают, нам придется понимать их основы.
Статья для новичков, это ИМХО хорошо.
А вот то что написано не очень.
SetWindowText(hwnd, "Новый заголовок окна");
Зачем в таком платформонезависимом материале такая специфичная для ОС функция, да ещё и из графического режима? Неужели в консоли ничего не нашлось?
Исторически символ занимает 1 байт, в этом случае он имеет тип char.
Известно что sizeof(char) == 1 и sizeof(любой тип) это целое число. То что char это один байт нигде не указано.
В свою очередь многобайтные кодировки можно разделить на кодировки с фиксированным количеством байтов — каждому символу соответствует одинаковое количество байтов, и «плавающие», в которых один символ может представляться разным количеством байтов в зависимости от его содержимого. К первым относятся кодировки типа Unicode, в которой каждый символ представлен двумя байтами, ко вторым — UTF-8 и др. Плавающие кодировки — отдельная тема, языки С/С++ не предлагают для них никакой поддержки.
В Unicode некоторые символы так же представлены последовательностями байт длины отличной от двух. Кажется кстати и японские иероглифы.
В С/С++ существует специальный тип для многобайтных символов — wchar_t
Просвятите, разве wchar_t стандартизирован?
размер передаваемых в функцию массивов нужно указывать отдельно, получить его в функции нельзя
Насколько я знаю массивы никогда не передаются. Даже если задекларировать в качестве параметра массив, всё равно будет передан указатель.
Напомню, что c массивом элементов типа char связан указатель на char
Что значит связан? Леночкой Гименея?
wchar_t sym;
sym=L'ab';
Это вообще не корретная запись. Вам должна выдатся ошибка или на худой конец предупреждение. Надо либо так
wchar_t sym;
sym='ab';
Лио так
wchar_t sym;
sym=L'a';
Существует специальный формат для записи символьных литералов – слеш, за которым идет код символа
Не слеш, а обратный слеш.
Применение же этих операций к строкам либо вообще запрещено
С каких это пор над указателями запрещена математика?
Снизить риск такого развития событий способна функция
Последний параметр – максимальное количество копируемых символов. Таким образом, передавая туда размер приемника, вы гарантируете, что функция никогда не выйдет за пределы выделенной памяти. Однако помните, что если исходная строка будет скопирована не полностью, нуль-терминатор не появится в результирующей строке. Его придется записать самостоятельно.
ПРЕДУПРЕЖДЕНИЕ
Никогда не забывайте контролировать используемую память!
Здесь стоило бы ИМХО упомянуть StrSafe.h Он хотя и не стандартный, но
1) Microsoft Visual C++ не самый забытый компилятор
2) Для новичков (и тех кто боится переполнения буффера) самое то.
3) Другие не стандартный функции от Microsoft в статье упоминаются
for (i=0;i<strlen(str);i++) {
// работа со строкой, не изменяющая ее длину
}
Я бы заменил на
for (unsigned int i = 0, len = strlen(str); i < len; i++) {
// работа со строкой, не изменяющая ее длину
}
Ну и дальше везде, где цикл.
Зачастую требуется преобразовать число в строку и наоборот. Есть несколько способов сделать это.
Во-первых, такие преобразования совсем несложно делать самостоятельно. Оставляю это в качестве домашнего задания
Ага Очень не сложно строку вида "1,23456-E37" преобразовать в число. Пустяки собственно.
Эти функции очень похожи на printf и scanf, за исключением того, что они работают не с консолью, а со строковым буфером. Для дополнительной информации об этих функциях см. документацию.
RTFM это конечно хорошо, только вот какую документацию смотреть?
Ну и вопрос не к автору. КАК ТАКУЮ СЫРУЮ СТАТЬЮ ПРОПУСТИЛИ????
a> Исторически символ занимает 1 байт, в этом случае он имеет тип char.
a> Известно что sizeof(char) == 1 и sizeof(любой тип) это целое число. a> То что char это один байт нигде не указано.
Именно байт. В C и C++ (unsigned) байт представляет собой минимально адресуемую
единицу памяти. Вкупе с требованием того, что все биты unsigned char значащие
и sizeof(char) == 1 байт, а также возможностью оперировать с фактически
произвольной памятью как с массивом (unsigned) char, это делает (unsigned) char
типом непосредственно представляющим байт.
Определение байта:
1.7 The fundamental storage unit in the C++ memory model is the byte.
A byte is at least large enough to contain any member of the basic execution
character set and is composed of a contiguous sequence of bits, the number
of which is implementation-defined.
Некоторые данные о (signed, unsigned) char:
3.9.1 Objects declared as characters (char) shall be large enough to store
any member of the implementation’s basic character set. <...> A char, a signed
char, and an unsigned char occupy the same amount of storage and have the same
alignment requirements (3.9); that is, they have the same object representation.
For character types, all bits of the object representation participate in
the value representation. For unsigned character types, all possible bit patterns
of the value representation represent numbers.
В каких единицах выражается sizeof:
5.3.3 The sizeof operator yields the number of bytes in the object
representation of its operand. <...> sizeof(char), sizeof(signed char) and
sizeof(unsigned char) are 1 <...>
a> a>
a> В С/С++ существует специальный тип для многобайтных символов — wchar_t
a> Просвятите, разве wchar_t стандартизирован?
Да. Это специальный тип, не являющийся typedef.
3.9.1/5 Type wchar_t is a distinct type <...>
a> a>
a> размер передаваемых в функцию массивов нужно указывать отдельно, получить
a> его в функции нельзя
a> Насколько я знаю массивы никогда не передаются. Даже если задекларировать a> в качестве параметра массив, всё равно будет передан указатель.
Передать массив можно, т.е. имя массива можно использовать в качестве аргумента. Принять массив по значению, конечно, нельзя, т.е. параметров типа
массив не бывает (указатели/ссылки на массив — другое дело). Но, по-моему,
именно это и сказано в статье
a> a>
a>
a> wchar_t sym;
a> sym=L'ab';
a>
a> Это вообще не корретная запись. Вам должна выдатся ошибка a> или на худой конец предупреждение.
Почему ты так считаешь? Напротив, ошибку выдавать компилятор права не имеет.
От реализации зависит только значение литерала:
2.13.2 1 <...> An ordinary character literal that contains more than one c-char
is a multicharacter literal. A multicharacterliteral has type int and
implementation-defined value. 1 <...> The value of a wide-character literal containing multiple c-chars
is implementation-defined.
a> Ну и вопрос не к автору. a> КАК ТАКУЮ СЫРУЮ СТАТЬЮ ПРОПУСТИЛИ????
По-моему, ты преувеличиваешь. Явные ляпы я вижу только в твоих замечаниях
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Именно байт.
the number of which is implementation-defined.
То есть хоть 4, хоть 17, хоть 32. Я имею ввиду где указано что байт в смысле архитектуры процессора == char?
Исторически символ занимает 1 байт, в этом случае он имеет тип char. При этом существуют и другие кодировки, в которых символ представляется, например, двумя байтами.
Может я и ошибаюсь, но речь здесь (судя по кодировкам) именно о процессорном байте. Хотя ладно пустяки. Забили. ПК>Да. Это специальный тип, не являющийся typedef.
Это был вопрос ПК>Передать массив можно, т.е. имя массива можно использовать в качестве ПК>аргумента. Принять массив по значению, конечно, нельзя, т.е. параметров типа ПК>массив не бывает (указатели/ссылки на массив — другое дело). Но, по-моему, именно это и сказано в статье
Неправда ваша. Указатели и массивы идут двумя разными пунктами, в то время как это уже на уровне языка одно и то же в смысле способа передачи в функцию.
размер передаваемых в функцию массивов нужно указывать отдельно, получить его в функции нельзя
такой подход не работает при использовании указателей, размер которых не зависит от длины последовательности, на которую они указывают.
То есть автор до кучи ещё и запутывает новичка (а статья, скажем сразу, для очень начинающих) о методе передачи массива. Вот от таких статей и берутся такие вопросы
ПК>Почему ты так считаешь? Напротив, ошибку выдавать компилятор права не имеет.
Я так считаю потому что L'ab' это 4(!) байта. 2 на L'a' и ещё 2 на L'b'.
ПК>По-моему, ты преувеличиваешь. Явные ляпы я вижу только в твоих замечаниях
Ладно погрячился, не сырая, а сыроватая. Но что-то явных ляпов в моих замечаниях нет (разве что про байт спорно, а вот многие другие ты пропустил, а молчание знак согласия), а вот статья явно не дописана. Ну не дожали автора, я же знаю как жмут ради дела, а здесь не дожали .
Здравствуйте, adontz, Вы писали:
ПК>> Именно байт.
a>
a> the number of which is implementation-defined.
a> То есть хоть 4, хоть 17, хоть 32. Я имею ввиду где указано что байт a> в смысле архитектуры процессора == char?
Формально это указать еще строже, чем потребовав, чтобы char представлял
минимально адресуемую единицу, имхо, сложно.
a> Может я и ошибаюсь, но речь здесь (судя по кодировкам) именно a> о процессорном байте. Хотя ладно пустяки. Забили.
Кодировки к "процессорным байтам" никакого отношения не имеют.
ПК>> Да. Это специальный тип, не являющийся typedef.
a> Это был вопрос
Хм... Разве я на него не ответил, дав ссылку на стандарт? Если нет,
сформулируй, пожалуйста, вопрос точнее.
a> Указатели и массивы идут двумя разными пунктами, a> в то время как это уже на уровне языка одно и то же в смысле a> способа передачи в функцию.
Это одно и то же с точки зрения получения в функции, а передача
происходит по-разному: для массива производится преобразование к указателю,
которое не делается в случае передачи непосредственно указателей.
ПК>> Почему ты так считаешь? Напротив, ошибку выдавать компилятор права ПК>> не имеет.
a> Я так считаю потому что L'ab' это 4(!) байта.
Нет, sizeof(L'ab') == sizeof(wchar_t)
a> 2 на L'a' и ещё 2 на L'b'.
Ты неверно понимаешь, как "работают" многосимвольные литералы. Типом L'...'
вне зависимости от количества символов остается wchar_t, равно как типом
'...' — char.
a> Ладно погрячился, не сырая, а сыроватая.
Статья, как статья Есть и хуже, есть и лучше.
a> многие другие ты пропустил, а молчание знак согласия
В данном случае, скорее, лени
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Ты неверно понимаешь, как "работают" многосимвольные литералы. Типом L'...' ПК>вне зависимости от количества символов остается wchar_t, равно как типом ПК>'...' — char.
Речь ведь не о том, что это объязательно не скомпилируется, речь о том что это не корректно. Значение L'ab' это уникодный символ 'a'. В то время как 'b' "пролетает".
Меня например компилятор об этом честно предупредил
test.cpp(6) : warning C4066: characters beyond first in wide-character constant ignored
a>> Ладно погрячился, не сырая, а сыроватая. ПК>Статья, как статья Есть и хуже, есть и лучше.
Успокоил
a>> многие другие ты пропустил, а молчание знак согласия ПК>В данном случае, скорее, лени
Здравствуйте, adontz, Вы писали:
ПК>> Ты неверно понимаешь, как "работают" многосимвольные литералы. Типом L'...' ПК>> вне зависимости от количества символов остается wchar_t, равно как типом ПК>> '...' — char.
a> Речь ведь не о том, что это объязательно не скомпилируется, речь о том что a> это не корректно.
Это может быть вполне корректным.
a> Значение L'ab' это уникодный символ 'a'. В то время как 'b' "пролетает".
Не обязательно. Компилятор может использовать 'b' для формирования сложного
символа совместно с 'a'.
a> Меня например компилятор об этом честно предупредил
Значит, твой компилятор этого не делает. Но это не означает, что указанная
последовательность "не корректна" в общем случае.
a>>> многие другие ты пропустил, а молчание знак согласия
ПК>> В данном случае, скорее, лени
a> Ну тогда не буду мешать
Don't worry, be happy С Новым годом!
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Ну, тут Павел по большей части ответил — но я, как автор, должен сам реагировать . A>
A>SetWindowText(hwnd, "Новый заголовок окна");
A>Зачем в таком платформонезависимом материале такая специфичная для ОС функция, да ещё и из графического режима? Неужели в консоли ничего не нашлось?
Я хотел продемонстрировать, что С-строки важны, например, при работе с API. В С++ C-строки используются очень мало.
A>
A>Исторически символ занимает 1 байт, в этом случае он имеет тип char.
A>Известно что sizeof(char) == 1 и sizeof(любой тип) это целое число. То что char это один байт нигде не указано.
Тут целиком присоединяюсь к Павлу. A>В Unicode некоторые символы так же представлены последовательностями байт длины отличной от двух. Кажется кстати и японские иероглифы.
Можно пример со ссылками? Действительно интересно. Я был уверен, что Unicode — всегда два байта.
A>Просвятите, разве wchar_t стандартизирован?
Да. См., например, Страуструпа.
A>Насколько я знаю массивы никогда не передаются. Даже если задекларировать в качестве параметра массив, всё равно будет передан указатель.
Присоединяюсь к Павлу. Попробую уточнить. Передаются в том смысле, что функция принимает эти данные и каким-то образом использует их.
A>
A>Напомню, что c массивом элементов типа char связан указатель на char
A>Что значит связан? Леночкой Гименея?
Именно так. Леночкой Гименеевой. Природа связи между массивами и указателями — очень обширная тема, чуть-чуть затронутая в начале.
A>
A>
A>wchar_t sym;
A>sym=L'ab';
A>
A>Это вообще не корретная запись. Вам должна выдатся ошибка или на худой конец предупреждение. Надо либо так
Страуструп, "Язык программирования С++, специальное издание":
Символьные литералы из расширенного набора записываются в виде L'ab', при этом количество символов между одиночными кавычками и их значение зависят от реализации и соответствуют типу wchar_t.
A>С каких это пор над указателями запрещена математика?
Попробуй, например, перемножить два указателя. Подсказка: см. стандарт 1998 г, параграф 5.6, пункт 2.
A>Здесь стоило бы ИМХО упомянуть StrSafe.h Он хотя и не стандартный, но A>1) Microsoft Visual C++ не самый забытый компилятор A>2) Для новичков (и тех кто боится переполнения буффера) самое то. A>3) Другие не стандартный функции от Microsoft в статье упоминаются
Я уже отметил, с какой целью я употребил функцию SetWindowText.
A>
A>for (unsigned int i = 0, len = strlen(str); i < len; i++) {
A> // работа со строкой, не изменяющая ее длину
A>}
A>
A>Ну и дальше везде, где цикл.
Считается, что и i, и str определены где-то ранее.
A>Ага Очень не сложно строку вида "1,23456-E37" преобразовать в число. Пустяки собственно.
А что, в самом деле трудно?
A>Эти функции очень похожи на printf и scanf, за исключением того, что они работают не с консолью, а со строковым буфером. Для дополнительной информации об этих функциях см. документацию. A>RTFM это конечно хорошо, только вот какую документацию смотреть?
В справке к своему компилятору, в стандарте, в книгах. Уж больно флагов там много, приводить все описание целиком.
A>Ну и вопрос не к автору. A>КАК ТАКУЮ СЫРУЮ СТАТЬЮ ПРОПУСТИЛИ????
Вопрос не ко мне — я отвечать не буду.
Здравствуйте, Vamp, Вы писали:
V>Ну, тут Павел по большей части ответил — но я, как автор, должен сам реагировать .
И это правильно! А я уже думал ты отсиживаешься, а оказывается мужик!
V>Я хотел продемонстрировать, что С-строки важны, например, при работе с API. В С++ C-строки используются очень мало.
Это ясно. Просто удивило что на таком материале вдруг всплыло WinAPI.
V>Тут целиком присоединяюсь к Павлу.
Ну вы меня уже и убедили
V>Можно пример со ссылками? Действительно интересно. Я был уверен, что Unicode — всегда два байта.
Surrogates
There is a need to support more characters than the 65,536 that fit in the 16-bit Unicode code space. For example, the Chinese speaking community alone uses over 55,000 characters. To answer this need, the Unicode Standard defines surrogates. A surrogate or surrogate pair is a pair of 16-bit Unicode code values that represent a single character. The first (high) surrogate is a 16-bit code value in the range U+D800 to U+DBFF. The second (low) surrogate is a 16-bit code value in the range U+DC00 to U+DFFF. Using surrogates, Unicode can support over one million characters. For more details about surrogates, refer to The Unicode Standard, version 2.0.
Windows 2000 introduces support for basic input, output, and simple sorting of surrogates. However, not all system components are surrogate compatible. Also, surrogates are not supported in Windows 95/98/Me.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/unicode_192r.asp
V>Присоединяюсь к Павлу. Попробую уточнить. Передаются в том смысле, что функция принимает эти данные и каким-то образом использует их.
Ну не каким-то. Вся суть в том что способ стандартизирован. В этом смысле 2 разных пункта: указатели и массивы — выглядят странно и запутывающе. Последнее (с учётом потенциальной аудитории) меня и огорчило.
V>Именно так. Леночкой Гименеевой. Природа связи между массивами и указателями — очень обширная тема, чуть-чуть затронутая в начале.
Не такая уж обширная. Просто надо сказать, что любой массив элементов типа TYPE можно расматривать и как указатель TYPE * на первый элемент. Ну и обратно указатель можно рассматривать как массив. Преобразования туда-сюда выполняются компилятором неявно, по мере необходимости. Именно из-за этих преобразований можно написать так
void f(char *);
char str[] = "text";
f(str); // Если бы преобразования не было, пришлось бы писать f(&str[0]);
Для начинающего вполне достаточно.
V>
V>Символьные литералы из расширенного набора записываются в виде L'ab', при этом количество символов между одиночными кавычками и их значение зависят от реализации и соответствуют типу wchar_t.
Ну вот так и напишите. А то я это склоне читать как присваивание 16битной переменной 32битного значения.
V>Попробуй, например, перемножить два указателя. Подсказка: см. стандарт 1998 г, параграф 5.6, пункт 2.
А складывать-вычитать?
A>>Здесь стоило бы ИМХО упомянуть StrSafe.h Он хотя и не стандартный, но A>>1) Microsoft Visual C++ не самый забытый компилятор A>>2) Для новичков (и тех кто боится переполнения буффера) самое то. A>>3) Другие не стандартный функции от Microsoft в статье упоминаются
V>Я уже отметил, с какой целью я употребил функцию SetWindowText.
Причём здесь SetWindowText?. Пункт 3 это намёк на itoa, ltoa
A>>for (unsigned int i = 0, len = strlen(str); i < len; i++)
V>Считается, что и i, и str определены где-то ранее.
Я про прения выше — типа строка константная, а считается её длина много раз.
V>А что, в самом деле трудно?
Мне не трудно, не хочу себя хвалить, но ты для специалистов моего уровня писал? Наверное несколько ниже не так ли?
V>В справке к своему компилятору, в стандарте, в книгах. Уж больно флагов там много, приводить все описание целиком.
Тогда лучше всего 2 ссылки. На главу стандарта и на MSDN.
V>Вопрос не ко мне — я отвечать не буду.
И не надо. Пиши много хороших статей — вот достойный ответ.
А>В данном фрагменте А>for (i=0;i<strlen(str);i++) { А> // работа со строкой, не изменяющая ее длину А>}
А>str — это const char*. Компилятор сможет заменить вызовы strlen(str) на константу?
#include <string.h>
int main (){
const char* s1="aaa";
const char* s2="aaaaaaaaaa";
int i1=strlen(s1);//i1=3
s1=s2;//
int i2=strlen(s1);//i2=10
}
То есть на этапе компилляции вычислять strlen от const char * нельзя. Если бы
const char* const s3="sdfdsfdsf";
то strlen(s3) могло бы быть заменено константой, хотя никто не гарантирует, что это будет правильным:
кто-нибудь свободо применить const_cast и все испортить
Здравствуйте, adontz, Вы писали:
V>> Можно пример со ссылками? Действительно интересно. Я был уверен, что V>> Unicode — всегда два байта.
В более новых версиях уже 4.
a>
a> refer to The Unicode Standard, version 2.0.
Ну, это уже очень старенький Unicode
a> Просто надо сказать, что любой массив элементов типа TYPE можно a> расматривать и как указатель TYPE * на первый элемент. a> Ну и обратно указатель можно рассматривать как массив. <...>
Хм... А разве именно это не говорится в начале статьи?
Предполагается, что читателю знакомы следующие особенности
связи между массивами и указателями:
массив можно привести к указателю на его первый элемент, что неявно
происходит при передаче массивов в функции, ожидающие указатели
информация о размере массива переданного таким образом в функцию теряется
в С не существует способа передать массив по значению с сохранением
его размера
указателя на первый элемент массива достаточно для работы со всем массивом,
при условии что нам известна его длина.
Если вышеприведенные высказывания вызывают у вас затруднения, рекомендую сначала
разобраться с этим вопросом, а уже потом читать эту статью.
A>>> Здесь стоило бы ИМХО упомянуть StrSafe.h <...>
V>> Я уже отметил, с какой целью я употребил функцию SetWindowText.
a> Причём здесь SetWindowText?. Пункт 3 это намёк на itoa, ltoa
В отличие от StrSafe.h, itoa, ltoa etc. поддерживаются многими компиляторами,
а не только VC++.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
V>>Я хотел продемонстрировать, что С-строки важны, например, при работе с API. В С++ C-строки используются очень мало. A>Это ясно. Просто удивило что на таком материале вдруг всплыло WinAPI.
Общеизвестное внешнее API, распространенная функция из него, идеальная демонстрация строкового литерала. Полагаю, MacApi известно гораздо меньше.
A>Не такая уж обширная. Просто надо сказать, что любой массив элементов типа TYPE можно расматривать и как указатель TYPE * на первый элемент. Ну и обратно указатель можно рассматривать как массив.
Ну,придираться, так придираться . указатель TYPE * — это TYPE**, то есть указатель на указатель. Точнее надо быть.
Во-вторых, именно это и сказано в начале статьи.
A>Ну вот так и напишите. А то я это склоне читать как присваивание 16битной переменной 32битного значения.
Ну, это лично Ваша склонность .
V>>Попробуй, например, перемножить два указателя. Подсказка: см. стандарт 1998 г, параграф 5.6, пункт 2. A>А складывать-вычитать?
Складывать указатели нельзя.
Их, правда, можно складывать с интегральными или перечислимыми типами. Вычитать можно.
Применение же этих операций к строкам либо вообще запрещено, либо, что еще хуже, их результат в большинстве случаев далек от ожидаемого.
Ну, так и есть. Например, результатом
char* s="Hell";
s+='o';
не будет str=="hello", хотя код скомпилируется. Вычитание и сложение указателей применительно ко строкам не позволяет складывать и вычитать строки в лексикографическом смысле.
V>>Я уже отметил, с какой целью я употребил функцию SetWindowText. A>Причём здесь SetWindowText?. Пункт 3 это намёк на itoa, ltoa
Они поддерживаются не только в MSVC.
A>
A>>>for (unsigned int i = 0, len = strlen(str); i < len; i++)
A>
V>>Считается, что и i, и str определены где-то ранее. A>Я про прения выше — типа строка константная, а считается её длина много раз.
А это откуда вообще взялось? Я еще тогда удивился. В тексте статьи сказано
// работа со строкой, не изменяющая ее длину
О константности ни слова. Впрочем, у некоторых людей завидная способность читая видеть то, что они хотят видеть, а не то, что написано.
V>>А что, в самом деле трудно? A>Мне не трудно, не хочу себя хвалить, но ты для специалистов моего уровня писал? Наверное несколько ниже не так ли?
Мне всегда трудно оценить сложность той или иной задачи, но если она решается "в лоб", то я склонен считать ее простой. В самом деле, функция-то из пары десятков строчек. И даже без (явных) автоматов. И кстати, статья ориентирована не столько на тех, кто не умеет программировать вообще, сколько на тех, кто не умеет программировать именно на С. А для человека с опытом работы на любом алгоритмическом языке поставленная задача вообще трудности не представляет.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>В более новых версиях уже 4.
Это не новые, это другие версии. 2-х байтный ещё никто не отменял и скорее всего им и будут пользоватся ещё очень долго.
ПК>Хм... А разве именно это не говорится в начале статьи?
Тем страннее, что потом массивы и указатели рассматриваются отдельно. К тому же примера нет. А начинающему пример очень важен.
Здравствуйте, adontz, Вы писали:
ПК>>В более новых версиях уже 4. A>Это не новые, это другие версии. 2-х байтный ещё никто не отменял и скорее всего им и будут пользоватся ещё очень долго.
Эээ... По-моему, ты путаешь кислое с пресным. Смотри здесь
Здравствуйте, achp, Вы писали:
A>Да нет, просто есть один, единый стандарт Уникод. Он определяет два набора символов
Стало любопытно, полез гуглить и почти сразу наткнулся на The Online Edition of The Unicode Standard, Version 3.0.
Здравствуйте, jazzer, Вы писали:
j> типом '...' является char только в случает, если там в кавычках всего j> один символ, а если несколько — это уже int.
И действительно...
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
J>В MacAPI тебе такое и не удастся проделать — там используются паскалевские строки, в которых в первом байте идет длина строки, и, соответственно, не нужен завершающий нуль, а получение длины строки сводится к простому чтению первого символа.
Век живи — век учись .
Вот еще одна причина к использованию именно WinAPI. ^)
M>ИМХО статья нужная. Может кто-то это всё и знает, но мне она понравилась.
Вероятно, в начале февраля. Если конечно примут, а не скажут, что судя по реакции на первую часть она никому не нужна .