Почему wcslen считает 1 дополнительный символ в argv[1]?
argv[1]
кажется, возвращает 1 дополнительный символ, чем то, что вводится. argv[2]
верно.
#include <stdio.h>
int main(int argc, wchar_t *argv[])
{
printf("%d %d\n",wcslen(argv[1]),wcslen(argv[2]) );
return 0;
}
Я использую mingw32 для компиляции. Я собираю с gcc myprog.c
,
Почему это так?
3 ответа
ожидает параметры типа
int
и
char**
(или что эквивалентно). Также есть необязательный третий параметр, который представляет собой массив строк окружения.
Но что происходит, так это то, что большинство компиляторов не заботятся о безопасности типов параметров для. Он с радостью позволяет вам объявить, что принимает любой тип аргументов (или не принимает аргументов), который вы хотите для argc и argv. Я думаю, что это в значительной степени историческое с обратной совместимостью с
C
сделать это. И в результате неявного приведения
char*[]
введите в
wchar_t*[]
, строки интерпретируются совершенно по-разному.
Поэтому неверно утверждать, что от wcslen вы получаете +1 больше, чем ожидалось. Это технически неопределенное поведение.
Два возможных исправления:
Простое исправление - это просто этот delcare второй параметр массив
char
струны вместо
wchar_t
струны.
int main(int argc, char* argv[])
Если ваш компилятор был Visual Studio и вы хотели, чтобы аргументы Unicode передавались, исправление заключалось бы в объявлении точки входа вашей программы как вместо
main
int wmain(int argc, wchar_t* argv[])
Вышеупомянутое исправление, безусловно, будет скомпилировано с mingw, но я не уверен, поддерживает ли компоновщик для включения
wmain
как точка входа в программу. Попробуйте и узнайте.
Вот цитата из черновика стандарта C, n1570.pdf:
5.1.2.2.1 Запуск программы
1 Функция, вызываемая при запуске программы, называется основной. Реализация не объявляет прототип для этой функции. Он должен быть определен с типом возврата int и без параметров:
int main(void) { /* ... */ }
или с двумя параметрами (именуемыми здесь как argc и argv, хотя могут использоваться любые имена, так как они являются локальными для функции, в которой они объявлены):
int main(int argc, char *argv[]) { /* ... */ }
или эквивалент;10) или каким-либо другим способом, определяемым реализацией.
10) Таким образом, int может быть заменено именем typedef, определенным как int, или тип argv может быть записан как char ** argv, и так далее.
Это должно быть довольно просто для понимания. Если ваша реализация поддерживает argv с типом wchar_t **, то она будет работать с вашей реализацией в зависимости от реализации. Если вам требуется переносимость, не полагайтесь ни на что, определяемое реализацией.