Перейти к содержанию
    

Возврат значения char */char const *

Имеется функция:

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 функцию, в которой сделать приведение к нужному типу. Но тогда, с низким уровнем оптимизации, функция не будет заинлайнена.

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

Может есть более элегантное решение?

Как бы так объявить алиас для данной функции с другим типом аргумента/возвращаемого значения?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Имеется функция:

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)

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Понятно, что можно объявить inline функцию, в которой сделать приведение к нужному типу. Но тогда, с низким уровнем оптимизации, функция не будет заинлайнена.
Не используйте столь низкие уровни оптимизации.

 

Немного жаль, что в языке нет элегантного способа это разрулить.
Смотря в каком языке. В плюсах есть, называется перегрузка функций. Можно объявить две функции с одинаковым именем но разными типами параметров. В зависимости от типа передаваемого параметра будет подставлен вызов соответствующей функции. В общем надо переходить на плюсы, даже если писать на них в стиле обычных Сей, просто постепенно добавляя использование все новых и новых плюсовых плюшек.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Причём код внутри одинаковый. Немного жаль, что в языке нет элегантного способа это разрулить.

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

 

Предложение такое:

const char* f2(const char* s);
#define f1(s) (char*)f2(s)

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

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

 

Не используйте столь низкие уровни оптимизации.

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

 

Смотря в каком языке. В плюсах есть, называется перегрузка функций.

Это я знаю (см. исходное сообщение). И это ведёт опять к тому-же - или два раза одно и то же тело описывать или вызывать через inline одно общее тело.

Вот если-б можно было один раз описать, а для второго списка аргументов использовать что-то типа typedef ;)

typedef Func1 Func2;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот если-б можно было один раз описать, а для второго списка аргументов использовать что-то типа typedef ;)

typedef Func1 Func2;

шаблоны (template) позволяют такие выкрутасы, но ИМХО, это еще более корявая реализация, чем двойное тело функции.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

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

Как жить? Жить и не тужить. Можно подумать, от того, что функция не будет заинлайнена, небо упадёт на землю. Это всё вредные предрассудки, избавляйтесь от них.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как жить? Жить и не тужить.

Тут есть тема (Не)доработки языков программирования, которые хотели ли бы вы

наверное надо туда тему перекинуть - пусть обмозгуют, обжуют :biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А как жить тогда? Ведь уже при уровне "Medium" не производится inlining, а при более высоких - отладка практически невозможна. :((
Отлаживайтесь в окне дизассемблера. Отладка в этом окне возможна при любом уровне оптимизации. Я делаю именно так.

 

или вызывать через inline одно общее тело.
Это лучше. А что, у вашего компилятор нет _Pragma("inline=forced")?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

шаблоны (template) позволяют такие выкрутасы, но ИМХО, это еще более корявая реализация, чем двойное тело функции.

Шаблон таже двойная (энная) реализация. И ябы не сказал что корявая.

По крайней мере для простых применений (какие я пользую) - самое-то.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Имеется функция:

char *StrFunc(char const *str) {}

Внутри она использует str именно как char const * (только чтение) и потом возвращает например: str+N (N - типа int).

Вариант :):

#define func(str) ((str)+N)

 

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

 

Самое близкое к описанному Вами поведение даст _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).

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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);

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

...

UPDATE. Чёрт, опять часть варнингов потерялась...

Вот именно.

 

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

Во-первых - перегрузка.

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

 

__builtin_constant_p

У меня IAR :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Какой? Возвращать union {char *; char const *;}; ?

Ну так задача-то была - чтобы при вызове не городить преобразований типов. А тут ещё более громоздкий вызов получается...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...