реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Возврат значения char */char const *
jcxz
сообщение May 10 2017, 10:28
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Имеется функция:
char *StrFunc(char const *str) {}
Внутри она использует str именно как char const * (только чтение) и потом возвращает например: str+N (N - типа int).
Но в качестве вх. аргумента в неё могут передаваться как char * так и char const * - нет проблем, приведение типа делается автоматом.
Но хочется, чтобы и возвращаемое значение было того же типа, что и передано: для char * - char *, для char const * - char const *.
Чтобы не было необходимости делать: char const *s; ... ; s = (char const *)StrFunc(s);
Понятно, что можно объявить inline функцию, в которой сделать приведение к нужному типу. Но тогда, с низким уровнем оптимизации, функция не будет заинлайнена.
Или можно перегрузить эту функцию с другим типом аргумента/возвращаемого значения - опят будут две функции, выполняющие одно действие.
Может есть более элегантное решение?
Как бы так объявить алиас для данной функции с другим типом аргумента/возвращаемого значения?
Go to the top of the page
 
+Quote Post
scifi
сообщение May 10 2017, 10:38
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(jcxz @ May 10 2017, 13:28) *
Имеется функция:
char *StrFunc(char const *str) {}
Внутри она использует str именно как char const * (только чтение) и потом возвращает например: str+N (N - типа int).

Функция принимает указатель на const, возвращает указатель по сути на тот же объект, но убирает const. Это нечестно.

То есть должно быть 2 функции:
Код
char* f1(char* s);
const char* f2(const char* s);

Причём код внутри одинаковый. Немного жаль, что в языке нет элегантного способа это разрулить. Предложение такое:
Код
const char* f2(const char* s);
#define f1(s) (char*)f2(s)

Проверка типов сохраняется, всё работает. Логично?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 10 2017, 11:41
Сообщение #3


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (jcxz @ May 10 2017, 13:28) *
Понятно, что можно объявить inline функцию, в которой сделать приведение к нужному типу. Но тогда, с низким уровнем оптимизации, функция не будет заинлайнена.
Не используйте столь низкие уровни оптимизации.

QUOTE (scifi @ May 10 2017, 13:38) *
Немного жаль, что в языке нет элегантного способа это разрулить.
Смотря в каком языке. В плюсах есть, называется перегрузка функций. Можно объявить две функции с одинаковым именем но разными типами параметров. В зависимости от типа передаваемого параметра будет подставлен вызов соответствующей функции. В общем надо переходить на плюсы, даже если писать на них в стиле обычных Сей, просто постепенно добавляя использование все новых и новых плюсовых плюшек.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
jcxz
сообщение May 10 2017, 11:52
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(scifi @ May 10 2017, 12:38) *
Причём код внутри одинаковый. Немного жаль, что в языке нет элегантного способа это разрулить.

Я об этом и говорю.

Цитата(scifi @ May 10 2017, 12:38) *
Предложение такое:
Код
const char* f2(const char* s);
#define f1(s) (char*)f2(s)

Проверка типов сохраняется, всё работает. Логично?

Плохое решение. Две имени (функций) выполняющие одно и то же действие. И придётся каждый раз думать - какое имя подставить.

Цитата(Сергей Борщ @ May 10 2017, 13:41) *
Не используйте столь низкие уровни оптимизации.

А как жить тогда? Ведь уже при уровне "Medium" не производится inlining, а при более высоких - отладка практически невозможна. sad.gif(

Цитата(Сергей Борщ @ May 10 2017, 13:41) *
Смотря в каком языке. В плюсах есть, называется перегрузка функций.

Это я знаю (см. исходное сообщение). И это ведёт опять к тому-же - или два раза одно и то же тело описывать или вызывать через inline одно общее тело.
Вот если-б можно было один раз описать, а для второго списка аргументов использовать что-то типа typedef wink.gif
typedef Func1 Func2;
Go to the top of the page
 
+Quote Post
novikovfb
сообщение May 10 2017, 11:56
Сообщение #5


Знающий
****

Группа: Участник
Сообщений: 518
Регистрация: 29-09-11
Пользователь №: 67 450



Цитата(jcxz @ May 10 2017, 15:52) *
Вот если-б можно было один раз описать, а для второго списка аргументов использовать что-то типа typedef wink.gif
typedef Func1 Func2;

шаблоны (template) позволяют такие выкрутасы, но ИМХО, это еще более корявая реализация, чем двойное тело функции.
Go to the top of the page
 
+Quote Post
scifi
сообщение May 10 2017, 12:19
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(jcxz @ May 10 2017, 14:52) *
Плохое решение. Две имени (функций) выполняющие одно и то же действие. И придётся каждый раз думать - какое имя подставить.

Зато типы возвращаемых значений разные. Поэтому вполне логично, что это должно отражаться в имени функции, то есть где-то там будет const. Меня другое волнует - нельзя взять адрес функции, это же макрос. Но это редко нужно.

Цитата(jcxz @ May 10 2017, 14:52) *
А как жить тогда? Ведь уже при уровне "Medium" не производится inlining, а при более высоких - отладка практически невозможна. sad.gif(

Как жить? Жить и не тужить. Можно подумать, от того, что функция не будет заинлайнена, небо упадёт на землю. Это всё вредные предрассудки, избавляйтесь от них.
Go to the top of the page
 
+Quote Post
jcxz
сообщение May 10 2017, 12:41
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(scifi @ May 10 2017, 14:19) *
Как жить? Жить и не тужить.

Тут есть тема (Не)доработки языков программирования, которые хотели ли бы вы
наверное надо туда тему перекинуть - пусть обмозгуют, обжуют biggrin.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 10 2017, 14:14
Сообщение #8


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (jcxz @ May 10 2017, 14:52) *
А как жить тогда? Ведь уже при уровне "Medium" не производится inlining, а при более высоких - отладка практически невозможна. sad.gif(
Отлаживайтесь в окне дизассемблера. Отладка в этом окне возможна при любом уровне оптимизации. Я делаю именно так.

QUOTE (jcxz @ May 10 2017, 14:52) *
или вызывать через inline одно общее тело.
Это лучше. А что, у вашего компилятор нет _Pragma("inline=forced")?



--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
k155la3
сообщение May 10 2017, 14:37
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848



Цитата(novikovfb @ May 10 2017, 14:56) *
шаблоны (template) позволяют такие выкрутасы, но ИМХО, это еще более корявая реализация, чем двойное тело функции.

Шаблон таже двойная (энная) реализация. И ябы не сказал что корявая.
По крайней мере для простых применений (какие я пользую) - самое-то.
Go to the top of the page
 
+Quote Post
Шаманъ
сообщение May 10 2017, 18:25
Сообщение #10


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(jcxz @ May 10 2017, 13:28) *
Имеется функция:
char *StrFunc(char const *str) {}
Внутри она использует str именно как char const * (только чтение) и потом возвращает например: str+N (N - типа int).

Вариант sm.gif:
Код
#define func(str) ((str)+N)


Это была больше шутка, впрочем иногда вполне годная wink.gif.

Самое близкое к описанному Вами поведение даст _Generic (стандарт С1х), как-то так:
Код
#define StrFunc(str)  _Generic((str), const char*: (const char*)__StrFunc(str), char*: __StrFunc(str))

Т.е. Вашу функцию делаете в виде char* __StrFunc(const char* str), а потом везде вызываете макрос StrFunc. Поведение будет точно такое, как Вы писали:
Цитата
Но хочется, чтобы и возвращаемое значение было того же типа, что и передано: для char * - char *, для char const * - char const *.
Чтобы не было необходимости делать: char const *s; ... ; s = (char const *)StrFunc(s);


Еще можно сделать макросы с использованием typeof или __auto_type (расширения GCC).
Go to the top of the page
 
+Quote Post
esaulenka
сообщение May 11 2017, 11:36
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



Что-то не понял, почему нельзя возвращать указатель на константу? Тогда оно "само" приведётся к неконстанте, если потребуется.

Код
char const *StrFunc(char const *str)
{
    return str + 5;
}

int main(void)
{
    const char str1[] = "Hello, world!\n";
    char str2[] = "Hello, world!\n";
    
    const char *res1 = StrFunc (str1);
    char *res2 = StrFunc (str2);
    
    printf(res1);
    printf(res2);
    return 0;
}



UPDATE. Чёрт, опять часть варнингов потерялась...
Код
warning: initialization discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
     char *res2 = StrFunc (str2);

Да-а, беда. Плюсы с перезагрузкой ждут Вас :-)


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение May 11 2017, 14:37
Сообщение #12


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



https://gcc.gnu.org/onlinedocs/gcc-4.4.7/gc...r-Builtins.html

__builtin_constant_p


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
jcxz
сообщение May 17 2017, 07:09
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(esaulenka @ May 11 2017, 13:36) *
Что-то не понял, почему нельзя возвращать указатель на константу? Тогда оно "само" приведётся к неконстанте, если потребуется.
...
UPDATE. Чёрт, опять часть варнингов потерялась...

Вот именно.

Цитата(esaulenka @ May 11 2017, 13:36) *
Да-а, беда. Плюсы с перезагрузкой ждут Вас :-)

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

Цитата(demiurg_spb @ May 11 2017, 16:37) *
__builtin_constant_p

У меня IAR sad.gif
Go to the top of the page
 
+Quote Post
krux
сообщение May 17 2017, 09:44
Сообщение #14


Профессионал
*****

Группа: Свой
Сообщений: 1 700
Регистрация: 2-07-12
Из: дефолт-сити
Пользователь №: 72 596



А вариант с union вам не подойдет ?


--------------------
провоцируем неудовлетворенных провокаторов с удовольствием.
Go to the top of the page
 
+Quote Post
jcxz
сообщение May 17 2017, 10:25
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(krux @ May 17 2017, 11:44) *
А вариант с union вам не подойдет ?

Какой? Возвращать union {char *; char const *;}; ?
Ну так задача-то была - чтобы при вызове не городить преобразований типов. А тут ещё более громоздкий вызов получается...
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 30th June 2025 - 14:27
Рейтинг@Mail.ru


Страница сгенерированна за 0.01399 секунд с 7
ELECTRONIX ©2004-2016