Здравствуйте. Хочется странного.
Можно ли заставить функцию отличить на входе явно записанный строковой литерал от обычной С-строки, полученной, например, из std::string?
Не суть важно — на этапе компиляции или уже в работе, но чтобы вызовы
void main()
{
f("one");
// отличались от
std::string s = "two";
f(s.c_str());
}
Вроде бы строковые литералы имеют тип массива, а не указателя на первый символ? Но массив нельзя сделать аргументом функции
Re: Можно ли отличить строковой литерал от С-строки?
Здравствуйте, Went, Вы писали: W>Здравствуйте. Хочется странного. W>Можно ли заставить функцию отличить на входе явно записанный строковой литерал от обычной С-строки, полученной, например, из std::string?
Скрытый текст
W>
W>void main()
W>{
W> f("one");
W> // отличались от
W> std::string s = "two";
W> f(s.c_str());
W>}
W>
W>Вроде бы строковые литералы имеют тип массива, а не указателя на первый символ?
Строковый литерал имеет тип const char* (указатель на первый символ). W>Но массив нельзя сделать аргументом функции
Так?
void f(char a[])
{
}
Попробуйте одновременно объявить
void f(char* a)
{
}
Можно сделать так:
void f(char* a)
{
}
void f(const char* a)
{
}
но оба Ваши вызова попадут в функцию с const параметром.
Первую функцию можно вызвать так:
char a[] = "abcde";
f(a);
Re: Можно ли отличить строковой литерал от С-строки?
Здравствуйте, Went, Вы писали:
W>Здравствуйте. Хочется странного. W>Можно ли заставить функцию отличить на входе явно записанный строковой литерал от обычной С-строки, полученной, например, из std::string?
платформозависимо скорее всего можно: проверять диапазон адресов.
если в секции .rdata/.rodata — то это литерал.
на windows/linux/osx скорее всего заставить работать можно.
Re: Можно ли отличить строковой литерал от С-строки?
Здравствуйте, Went, Вы писали: W>Можно ли заставить функцию отличить на входе явно записанный строковой литерал от обычной С-строки, полученной, например, из std::string? W>Не суть важно — на этапе компиляции или уже в работе, ...
На правах бреда (очевидно, не портируемого и со сладкими грабельками в травке).
По стандарту, строковые литералы имеют static storage duration, т.е. память под
них выделяется статически. MS VC++, например, размещает такие строки внутри
самого модуля. Зная эту особенность реализации, можно сделать проверку:
if ( (p >= ImageBase) && (p < (ImageBase + ImageSize)) ) {
printf("'p' is a string literal.\r\n");
} else {
printf("'p' is not a string literal.\r\n");
}
ImageBase модуля (exe/dll) обычно уже известен (см. параметры WinMain/DllMain), а
ImageSize можно получить с помощью GetModuleInformation.
Скрытый текст
Думал минут 5, стоит или нет постить такой бред
Re: Можно ли отличить строковой литерал от С-строки?
Здравствуйте, Went, Вы писали:
W>Здравствуйте. Хочется странного. W>Можно ли заставить функцию отличить на входе явно записанный строковой литерал от обычной С-строки, полученной, например, из std::string? W>Не суть важно — на этапе компиляции или уже в работе, но чтобы вызовы W>
void main()
{
f("one");
// отличались от
std::string s = "two";
f(s.c_str());
}
W>Вроде бы строковые литералы имеют тип массива, а не указателя на первый символ? Но массив нельзя сделать аргументом функции
Здравствуйте, okman, Вы писали:
O>По стандарту, строковые литералы имеют static storage duration, т.е. память под O>них выделяется статически. MS VC++, например, размещает такие строки внутри O>самого модуля. Зная эту особенность реализации, можно сделать проверку...
Да, это самый очевидный вариант. Если компилятор различить не может, то только так. А можно еще попытаться туда что-то записать, и если Access Violation, то это статика
Re[2]: Можно ли отличить строковой литерал от С-строки?
А можно для простых смертных описать в двух словах, за счет чего это работает ?
И работает ли (C++14 на ideone.com вместо "0012" выдал "2212": https://ideone.com/CxhHRf) ?
Re[2]: Можно ли отличить строковой литерал от С-строки?
Здравствуйте, VTT.
О, тема Я как раз думал в таком направлении, но не догадался, что можно убрать очевидную перегрузку на const char*, в которую мирно сливались все варианты.
Re[3]: Можно ли отличить строковой литерал от С-строки?
Здравствуйте, okman, Вы писали:
O>А можно для простых смертных описать в двух словах, за счет чего это работает ? O>И работает ли (C++14 на ideone.com вместо "0012" выдал "2212": https://ideone.com/CxhHRf) ?
Здравствуйте, ELazin, Вы писали:
W>>Можно ли заставить функцию отличить на входе явно записанный строковой литерал от обычной С-строки, полученной, например, из std::string?
EL>Не совсем ответ на вопрос, но можно с помощью макросов добиться того, чтобы в функцию нельзя было передать динамическую строку:
EL>
EL>конкатенация будет работать только для статических строк, в противном случае — ошибка компиляции
для пишущих макросы в нижнем регистре в аду есть отдельный котел,
но с этим кодом проблема еще и в том, что он будет работать не для статических строк, а только для прямо подставленных строковых литералов
auto & sz_text("ooops");
foo(sz_text); // error
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Re[4]: Можно ли отличить строковой литерал от С-строки?
Здравствуйте, VTT, Вы писали:
VTT>обычный добротный код на C++11, готовый к переводу в ближайшем будущем на C++14 с его return type deduction
Обычно даже в языках с тотальным выводом типов (хаскель, например) сигнатуру функциям рекомендуют явно прописывать. В расте вывод тип для переменных и лямбд есть, но сигнатуры у функций опять же обязательны.
Разве удобно использовать "return type deduction" для всех-всех функций?
Re[5]: Можно ли отличить строковой литерал от С-строки?
Здравствуйте, DarkEld3r, Вы писали:
DE>Обычно даже в языках с тотальным выводом типов (хаскель, например) сигнатуру функциям рекомендуют явно прописывать. В расте вывод тип для переменных и лямбд есть, но сигнатуры у функций опять же обязательны. DE>Разве удобно использовать "return type deduction" для всех-всех функций?
Я пришел к выводу, что лучше давать методам названия, позволяющие сразу понять, возвращают ли они что-то (и что именно) или нет.
например:
вместо int Area() писать auto Get_Area()
вместо int UpdateArea() писать auto Get_UpdatedArea()
вместо interator begin() писать auto Get_BeginIterator()
вместо t_HitTestResult HitTest() писать auto Get_HitTestResult()
вместо bool visible() и void visible(bool new_visible) писать auto Is_Visible() и Set_Visible(bool visible)
Обычно если метод что-то возвращает (т.е. в его задачи входит действие по возвращению результата), то и название получаются типа Get_Something, Is_Something, Make_Something и т.п.
Ну и плюс автоматический вывод типа уменьшает количество писанины, облегчает внесение изменений и рефакторинг.
Мне кажется, что автоматический вывод типа возвращаемого значения очень похож на добавленный в C++11 вывод типа переменной в плане применимости и полезности.
Сейчас переменный по большей части объявляются с auto, и так же с методами будет.
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Здравствуйте, VTT, Вы писали:
VTT>Я пришел к выводу, что лучше давать методам названия, дающие ясно понять, возвращают ли они что-то (и что именно) или нет.
Так же делаю.
И у нас auto для переменных в соглашениях прописано и на ревью на это указывают, если вдруг кто забыл. Но вот auto в качестве возвращаемого значения... Может, конечно, это просто консервативность.
Re[3]: Можно ли отличить строковой литерал от С-строки?
VTT>для пишущих макросы в нижнем регистре в аду есть отдельный котел,
как пьяный до березы..
а) это всего навсего пример б) есть огромное количество примеров обратного в стандартной библиотеке и не только (в той же APR)
VTT>но с этим кодом проблема еще и в том, что он будет работать не для статических строк, а только для прямо подставленных строковых литералов
Так вопрос собственно в том и был, чтобы отличить строковый литерал от указателя на char.