Передать char * методу, ожидающему unsigned char *

Я работаю над некоторым встроенным устройством, имеющим SDK. Он имеет такой метод, как:

MessageBox(u8*, u8*); // u8 is typedefed unsigned char when I checked 

Но я видел в своих примерах код, например:

 MessageBox("hi","hello"); 

прохождение указателя char без броска. Может ли это быть четко определено? Я спрашиваю, потому что я запустил какой-то инструмент над кодом, и он жаловался на несоответствие выше:

 messageBox("Status", "Error calculating \rhash"); diy.c 89 Error 64: Type mismatch (arg. no. 1) (ptrs to signed/unsigned) diy.c 89 Error 64: Type mismatch (arg. no. 2) (ptrs to signed/unsigned) 

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

И также было бы неплохо узнать, что является правильным способом передать строку в методы SDK, ожидающие unsigned char* не вызывая нарушения ограничений?

Это нарушение ограничений, поэтому технически оно не определено, но на практике это не проблема. Однако вы должны использовать эти аргументы, чтобы отключить эти предупреждения. Альтернативой усечению вашего кода уродливыми приведениями является определение встроенной функции:

 static inline unsigned char *ucstr(const char *str) { return (unsigned char *)str; } 

И используйте эту функцию везде, где вам нужно передать строки API, которые (ошибочно) принимают аргументы unsigned char * :

 messageBox(ucstr("hi"), ucstr("hello")); 

Таким образом, вы не получите предупреждения, сохраняя при этом некоторую безопасность.

Также обратите внимание, что messageBox должен принимать аргументы const char * . Этот SDK использует сомнительные соглашения.

Проблема сводится к тому, что она определяется реализацией, является ли char unsigned или signed .

Компиляторами, для которых нет ошибки, будут те, для которых char фактически unsigned . Некоторые из них (особенно те, которые на самом деле являются компиляторами на C ++, где char и unsigned char – разные типы) выдают предупреждение. С этими компиляторами преобразование указателя в unsigned char * будет безопасным.

Компиляторами, которые сообщают об ошибке, будут те, для которых char фактически signed . Если компилятор (или хост) использует ASCII или аналогичный набор символов, а символы в строке могут быть распечатаны, то преобразование строки в unsigned char * (или, лучше, в const unsigned char * которая позволяет исключить константу из строковых литералов ) является технически безопасным. Тем не менее, эти преобразования потенциально небезопасны для реализаций, которые используют разные наборы символов ИЛИ для строк, содержащих непечатаемые символы (например, значения signed char типом signed char которые являются отрицательными, и значения unsigned char больше 127). Я говорю о потенциально опасном, потому что то, что происходит, зависит от того, что делает вызываемая функция, например, проверяет ли значение отдельных символов? он проверяет отдельные биты отдельных символов в строке? Последнее состоит в том, что если вызываемая функция хорошо разработана, одна из причин примет указатель на unsigned char * .

То, что вам нужно сделать, сводится к тому, что вы можете предположить о целевой машине, а также ее char и unsigned char – и что функция выполняет с аргументом. Самый общий подход (в том смысле, что он работает для всех наборов символов и независимо от того, signed ли char или unsigned ) заключается в создании вспомогательной функции, которая копирует массив char в другой массив unsigned char . Работа этой вспомогательной функции будет зависеть от того, как (и если) вам нужно обработать преобразование signed char значений signed char со значениями, которые являются отрицательными.