Тип литья в C для стандартной функции - PullRequest
2 голосов
/ 22 марта 2012

Я работаю над проектом C (все еще довольно новым для C) и пытаюсь удалить все предупреждения при его компиляции.

Оригинальные кодеры этого проекта создали тип с именем dyn_char(динамический char arr) и это тип unsigned char *.Вот копия одного из предупреждений:

предупреждение: аргумент # 1 несовместим с прототипом: prototype: указатель на символ: "... / stdio_iso.h", аргумент строки 210: указатель наchar без знака

Они также используют множество стандартных строковых функций, таких как strlen();, поэтому способ удаления этих предупреждений выглядит следующим образом:

strlen((char *)myDynChar);

Я могу сделать этоно некоторые файлы содержат сотни таких предупреждений.Я мог бы найти и заменить, чтобы найти strlen( и заменить на strlen((char*), но есть ли лучший способ?

Можно ли использовать макрос, чтобы сделать что-то подобное?Может быть, что-то вроде этого:

#define strlen(s) strlen((char *)s)

Во-первых, будет ли это работать?Во-вторых, если это так, разве это плохая идея?

Спасибо!

Ответы [ 3 ]

4 голосов
/ 22 марта 2012

Это досадная проблема, но вот мои два цента:

Во-первых, если вы можете с уверенностью изменить тип dyn_char на просто char *, я бы это сделал.Возможно, если у вас есть надежная тестовая программа или что-то еще, вы можете попробовать ее и посмотреть, работает ли она по-прежнему?

Если нет, насколько я вижу, у вас есть два варианта: исправить то, что входит в strlen(),или пусть ваш компилятор игнорирует эти предупреждения (или игнорирует их самостоятельно)!Я не из тех, кто игнорирует предупреждения, за исключением случаев, когда это необходимо, но для исправления того, что входит в strlen ...

Если ваш базовый тип равен unsigned char *, тогда приведение того, что входит в strlen(), в основномуказав компилятору допустить, что аргумент для целей передачи strlen() является char *.Если strlen() - единственное место, которое вызывает проблему, и вы не можете безопасно изменить тип, то я бы посоветовал поиск и замену для добавления в приведениях как предпочтительный вариант.Вы могли бы переопределить strlen с помощью #define, как вы и предлагали (я только что попробовал, и это сработало для меня), но я бы настоятельно рекомендовал не делать этого.Во всяком случае, я бы поискал-заменил strlen() на USTRLEN() или что-то еще (поддельное имя функции), а затем использовал бы это в качестве макроса приведения.Прозрачное переопределение функций библиотеки C с вашими собственными именами - это кошмар обслуживания!

Два аспекта: во-первых, вы используете другое имя.Во-вторых, вы используете все заглавные буквы, как это принято для определения такого макроса.

1 голос
/ 22 марта 2012

Вы можете определить функцию:

char *uctoc(unsigned char*p){ return (char*)(p); }

и выполнить поиск заменив strstr(x на strstr(uctoc(x).По крайней мере, вы можете иметь некоторую проверку типов.Позже вы можете конвертировать uctoc в макрос для производительности.

1 голос
/ 22 марта 2012

Это может или не может работать

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

(Visual Studio stdlib делает много интересных вещей с макросами в <string.h>. strcpy определяется следующим образом:

__DEFINE_CPP_OVERLOAD_STANDARD_FUNC_0_1(char *, __RETURN_POLICY_DST, __EMPTY_DECLSPEC, strcpy, _Pre_cap_for_(_Source) _Post_z_, char, _Dest, _In_z_ const char *, _Source))

Я бы совсем не удивился, если бы #defining strcpy сломал это) `

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

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

...