Почему strtol возвращает неправильное значение?

char xs[7] = {'0','0','0','1','0','1','0'};
long ss = strtol(xs, NULL, 2);

после 2-й строки ss 2147483647, есть идеи? следующий код находится в цикле (снаружи он работает нормально)


person user123454321    schedule 17.12.2014    source источник
comment
xs[] отсутствует завершение нулевого символа. Попробуйте char xs[7+1] = {'0','0','0','1','0','1','0',0};   -  person chux - Reinstate Monica    schedule 17.12.2014
comment
@chux, вероятно, легче увидеть, когда написано char xs[7+1] = {'0','0','0','1','0','1','0',NULL}; синтаксический сахар, очевидно, ;-P   -  person SnakeDoc    schedule 17.12.2014
comment
@SnakeDoc Лучше использовать 0 или '\0' для нулевого символа, чем NULL, который является нулевым указателем.   -  person chux - Reinstate Monica    schedule 17.12.2014
comment
Или еще лучше: char xs[7] = "0001010";   -  person John Bode    schedule 17.12.2014
comment
@chux ты прав. Тогда я бы использовал '\0', так как при быстром сканировании источника он будет легче выделяться (vim выделит его и т. д.).   -  person SnakeDoc    schedule 17.12.2014
comment
@John Bode char xs[7] = "0001010"; - не очень хорошая идея, поскольку в нем также нет разделителя нулевого символа. Возможно, вы имели в виду char xs[7+1] = "0001010"; или char xs[] = "0001010";   -  person chux - Reinstate Monica    schedule 17.12.2014
comment
или даже char xs[ ] = {'0','0','0','1','0','1','0',0}; подойдет.   -  person Sourav Ghosh    schedule 17.12.2014
comment
Этот вопрос кажется не по теме, потому что проблему можно решить, внеся небольшое изменение в код.   -  person R Sahu    schedule 17.12.2014
comment
strtol требует строку для ввода. строка завершается нулевым символом. «0» — это 0x30, нулевой символ — это 0x00. предложить добавить '\ 0' к списку символов в 'xs'   -  person user3629249    schedule 17.12.2014
comment
@chux - не хватает кофеина. Предполагалось оставить 7 выключенным.   -  person John Bode    schedule 18.12.2014


Ответы (1)


strtol ожидает строку с завершением NUL. Ваше объявление массива создает массив из 7 символов и заполняет все 7 позиций данными, отличными от NUL. Таким образом, strtol фактически продолжает поиск в стеке (или в памяти) до тех пор, пока не найдет завершающий символ.

У вас есть несколько вариантов объявления массива char и его правильной инициализации. Если это массив только для чтения, я предпочитаю:

char xs[] = "0001010";

который создаст массив, достаточно большой для хранения строкового литерала (включая завершающий NUL).

Другие варианты показаны в комментариях выше

char xs[7+1] = "0001010\0";
char xs[7+1] = {'0','0','0','1','0','1','0',0};
char xs[ ] = {'0','0','0','1','0','1','0',0};

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

В первом примере выше \0 — управляющая последовательность, представляющая символ ASCII NUL. Это предпочтительнее простого 0, потому что (а) он имеет правильный тип (char) для включения в строковый литерал, и (б) большинство редакторов, знающих синтаксис, подсветят его, поскольку NUL в середине литерала может иметь удивительные результаты. Например

   strlen("abc\0def") == 3
person kdopen    schedule 17.12.2014
comment
char xs[7+1] = "0001010\n"; выглядит подозрительно. - person Sourav Ghosh; 17.12.2014
comment
'\0' и 0 оба имеют тип int - person M.M; 17.12.2014
comment
'\0' можно присвоить типу int, как и 'A', но базовый тип — символьный литерал. - person kdopen; 17.12.2014