Привет, я написал небольшую тестовую программу, чтобы проверить, как функция, которую я написал, для преобразования строки (шестнадцатеричного числа) в целое число без знака, и я обнаружил, что код ведет себя по-разному в зависимости от используемого компилятора или системы.Почему strtoul не работает должным образом?
я составил код, приведенный ниже на:
(1) ideone С ++ 4.3.2 https://ideone.com/LlcNWw
(2) G ++ 4.4.7 на centos6 (64bits)
(3) G ++ 4.6.3 по принципу ubuntu12 (64бит)
(4) г ++ 4.9.3 в виде Cygwin (32бит) среды
Как и ожидалось (1) и (4) возвращение и это именно правильный результат, как 1-го значения «0x210000000» является большой для 32-битного значения ....
Error while converting Id (0x210000000).
success
но (2) и (3) возвращает
success
success
Таким образом возникает вопрос, почему же простой код C сборка на другой платформе с другим компилятором возвращает тот же результат ... и strtoul почему»(„0x210000000“ , ....) 'не устанавливает «errno» в «ERANGE», чтобы сказать, что бит 33-37 находится за пределами допустимого диапазона.
болееслед на платформу (3) дают:
Id (0x210000000) as ul = 0x10000000 - str_end - errno 0.
sucess
Id (0x10000000) as ul = 0x10000000 - str_end - errno 0.
sucess
/* strtoul example */
#include <stdio.h> /* printf, NULL */
#include <stdlib.h> /* strtoul */
#include <errno.h>
signed int GetIdentifier(const char* idString)
{
char *str_end;
int id = -1;
errno = 0;
id = strtoul(idString, &str_end, 16);
if (*str_end != '\0' || (errno == ERANGE))
{
printf("Error while converting Id (%s).\n", idString);
return -1;
}
// Return error if converted Id is more than 29-bit
if(id > 0x1FFFFFFF)
{
printf("Error: Id (%s) should fit on 29 bits (maximum value: 0x1FFFFFFF).\n", idString);
return -1;
}
printf("sucess\n");
return id;
}
int main()
{
GetIdentifier("0x210000000");
GetIdentifier("0x10000000");
return 0;
}
0x210000000 => более 4 октетов, а не UL, но ULL – Garf365
Различные целые типы и их размеры упоминаются очень рано в любой порядочной книге программирования C начального уровня. И вообще, использование 'int' или любого другого подписанного типа для хранения шестнадцатеричного числа не имеет никакого смысла. Как вы думаете, strto ** ul ** делает? Убедитесь, что предупреждения компилятора включены. – Lundin
BTW: 'if (* str_end! = '\ 0' || (errno == ERANGE))' не удается обнаружить никакого преобразования, как в 'id = strtoul (" ", & str_end, 16);' Предложить 'if (str_end == idString || * str_end! = '\ 0' || (errno == ERANGE)) ' – chux