ошибка C3861: 'strtoll': идентификатор не найден - PullRequest
2 голосов
/ 23 ноября 2011

Основная проблема, с которой я здесь сталкиваюсь, заключается в том, что strtoll() помечается как ошибка в VC 2010 (error C3861: 'strtoll': identifier not found). Будет ли он делать то же самое, если я заменю его на strtol()?

unsigned int get_uintval_from_arg(int argc, int index, char **argv,
                                  unsigned int lower_bound, unsigned int upper_bound) 
{  
    unsigned int return_val=0;

    if (index + 1 <= argc - 1)
    {
        return_val=(unsigned int)strtoll(argv[index+1],NULL,10);
        if (errno == EINVAL || errno== ERANGE) 
        {
            fprintf(stderr, "Could not parse argument %s for switch %s!\n",
                    argv[index], argv[index+1]);
            return 0;
        }
    }
    // ....... I will post the remaining part of the code if necessary 
    .......
}

Ответы [ 4 ]

5 голосов
/ 23 ноября 2011

Поскольку ваш return_val является unsigned int, вам, вероятно, следует использовать strtoul(), который был стандартным с C89 и поэтому поддерживается MSVC (тогда как strtoll() был стандартным только с C99 и не поддерживаетсяMSVC).

Ваше тестирование условий ошибки не подходит.Вам нужно установить errno в ноль перед вызовом функции преобразования;Вам также необходимо определить, была ли сообщена ошибка, что сложнее, чем кажется.

Раздел §7.20.1.4 «Функции strtol, strtoll, strtoul и strtoull» стандарта C99 гласит:

Возвращает

Функции strtol, strtoll, strtoul и strtoull возвращают преобразованное значение, если оно есть.Если преобразование не может быть выполнено, возвращается ноль.Если правильное значение находится за пределами диапазона представимых значений, возвращается LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX, ULONG_MAX или ULLONG_MAX (в соответствии с типом возврата и знаком значения, если есть), а значение макроса ERANGE равнохранится в errno.

. Вы также должны прочитать значение, сохраненное в параметре endptr, в функции преобразования, чтобы сказать, что преобразование не было выполнено (в отличие от действительного нуля).был преобразован).

Если последовательность объекта пуста или не имеет ожидаемой формы, преобразование не выполняется;значение nptr сохраняется в объекте, на который указывает endptr, при условии, что endptr не является нулевым указателем.

Итак, вы должны написать код, подобный этому (безпроверка на EINVAL, потому что в стандарте не упоминаются эти функции, устанавливающие errno в EINVAL):

unsigned int return_val=0;

if (index + 1 <= argc - 1)
{
    char *end;
    unsigned long ul;
    errno = 0;
    ul = strtoul(argv[index+1], &end, 10);
    if ((ul == 0 && end == argv[index+1]) ||
        (ul == ULONG_MAX && errno == ERANGE) ||
        (ul > UINT_MAX))
    {
        fprintf(stderr, "Could not parse argument %s for switch %s!\n",
                argv[index], argv[index+1]);
        return 0;
    }
    retval = (unsigned int)ul;
}

Обратите внимание, что это проще, чем проверка для целочисленного преобразования со знаком, который должен учитывать отрицательное значение <type>_MIN limit, а также предел <type>_MAX.

Также обратите внимание, что вы действительно должны записать результат в unsigned long, а затем проверить, соответствует ли он вашему назначенному диапазону, который может быть ограничен UINT_MAX (которыйможет быть меньше, чем ULONG_MAX в Unix-подобной 64-битной среде).

1 голос
/ 23 ноября 2011

В Visual studio вместо этого используйте метод _strtoi64(). Имеет те же параметры, что и strtoll.

Для совместимости вы можете просто использовать определение, чтобы обернуть его как strtoll (если вам нужна переносимость), например

#if defined(_MSC_VER)
#define strtoll _strtoi64
#endif
0 голосов
/ 23 ноября 2011

Для ваших целей вы должны использовать strtoul , поскольку вы конвертируете в тип unsigned long, а не в тип signed long long (что и делает strtoll).Если вам нужно прочитать в long long с, используйте Microsoft _strtoi64 ;вы можете использовать #define s, чтобы переименовать его в strtoll на платформах Microsoft, или написать функцию-обертку в специфический для Windows файл shims переносимости (с вашим собственным прототипом для него в частном заголовке).

0 голосов
/ 23 ноября 2011

strtol() - правильная библиотечная функция для long.Для переносимости объявите return_val как long или unsigned long.Если последнее, посмотрите, предлагает ли MSVC strtoul().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...