Как преобразовать int в короткий int в C?

Допустим, у меня есть char array[5] = {'1','2','3','4','\0'};.

Если мне нужно целое число, я могу просто использовать функцию atoi():
int num = atoi(array);

Как я могу получить значение как короткое/короткое целое?

Конечно, при условии, что значение соответствует шорту.

Мне нужно вызвать atoi() и решить это с помощью битового сдвига? Хотя я не совсем знаком с этим.


person Jo Michaelis    schedule 17.01.2021    source источник
comment
short int num = atoi(array);. Конечно, это зависит от того, что вы хотите делать, когда число выходит за пределы диапазона для короткого целого числа, было бы лучше описать этот вопрос.   -  person M.M    schedule 17.01.2021
comment
О, хорошо, конечно. Разве это не терпит неудачу, когда у меня есть отрицательное целое, и я хочу, чтобы короткое тоже было отрицательным?   -  person Jo Michaelis    schedule 17.01.2021
comment
также работает с негативом.   -  person Jean-François Fabre    schedule 17.01.2021
comment
Нет (пока значение находится в пределах диапазона для короткого int)   -  person M.M    schedule 17.01.2021
comment
Хорошо, отлично. Спасибо!   -  person Jo Michaelis    schedule 17.01.2021
comment
Может представлять интерес: stackoverflow.com/questions /18276225/convert-int-to-short-in-c   -  person Werner Henze    schedule 17.01.2021


Ответы (2)


Нет ASCII для короткой функции, https://en.cppreference.com/w/c/string/byte/atoi перечисляет только atoi для ascii до int, atol для ascii до long и atoll для ascii до long long.

Но вы можете использовать atoi для преобразования в int, а затем просто привести к short. Конечно, это не проверит, находится ли число в диапазоне short. Возможно, вам придется проверить это самостоятельно с помощью чего-то вроде SHRT_MIN <= i && i <= SHRT_MAX.

int num = atoi(array);
short s = (short)num;

или просто конвертировать напрямую:

short s = (short)atoi(array);

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

short s = atoi(array);  // Implicit cast
person Werner Henze    schedule 17.01.2021
comment
Приведение не требуется, поскольку существует неявное преобразование - person M.M; 17.01.2021
comment
было бы неплохо иметь какую-то проверку переполнения, хотя - person Jean-François Fabre; 17.01.2021
comment
@M.M Во мне был программист на C++ :). - person Werner Henze; 17.01.2021
comment
В C++ это тоже не обязательно, кстати - person M.M; 17.01.2021
comment
@MM Это правда, и в полном ответе следует упомянуть об этом, однако явное приведение показывает намерение и с меньшей вероятностью будет исправлено последующим сопровождающим. Большинство инструментов статического анализа, например, будут помечать предупреждение при назначении меньшего типа, и сопровождающий может решить эту проблему, ошибочно изменив тип, а не применив явное приведение. - person Clifford; 17.01.2021
comment
@Clifford существенное изменение кода, вероятно, будет лучшим решением, чем использование литого молотка (поскольку этот подход неудобен для работы со значениями, выходящими за пределы диапазона), трудно сказать только из опубликованного фрагмента - person M.M; 17.01.2021
comment
@WernerHenze Вы должны были сохранить явное приведение и добавить пример неявного приведения в качестве третьего (и, вероятно, опрометчивого) варианта. Есть причины, по которым вы можете использовать явное приведение типов, как указано выше. - person Clifford; 17.01.2021
comment
Но вы должны помнить, что ваш шорт может переполниться, и это неопределенное поведение. - person 0___________; 17.01.2021
comment
@M.M Согласен. Используя явное приведение типов, вы говорите Я сделал эту опасную вещь преднамеренно — надеюсь, это оправдано комментарием. Без приведения никто не знает, является ли это преднамеренной или семантической ошибкой. Возможно, входная строка ограничена или проверена в другом месте и является предварительным условием ввода. Я думаю, что это выходит за рамки вопроса, чтобы иметь дело с проверкой диапазона; в качестве комментария - достаточно справедливо. - person Clifford; 17.01.2021
comment
@Clifford это приводит к безопасному коду, который иногда можно увидеть (void)func((int)34, (char *)mybuff, (const short)x); - person 0___________; 17.01.2021
comment
@P__JsupportswomeninPoland Это правда, что приведение всего позволяет обойти статический анализ. Есть и порочные примеры. Полное согласование типов предпочтительнее, чем приведение типов, но чтобы узнать, уместно ли это в данном случае, нам нужно увидеть больше кода. На первый взгляд, нет никаких доказательств того, что это неуместно в данном случае. Все предупреждения о вреде для здоровья действительны, но я не думаю, что это заслуживает внимания в ответе - вот и все. - person Clifford; 18.01.2021

Более безопасная версия, чем простое литье.

#include <stdlib.h>
#include <limits.h>

short getshort(const char *num, int *errcode) 
{    
    int result = atoi(num);

    if(errcode)
    {
        *errcode = 0;
        if(result > SHRT_MAX) *errcode = 1;
        else if(result < SHRT_MIN) *errcode = -1;
    }
    return result;
}
person 0___________    schedule 17.01.2021
comment
По размышлению, несмотря на мои комментарии в другом месте, в данном случае это имеет смысл. Накладные расходы на проверку диапазона тривиальны по сравнению с преобразованием atoi. В общем случае вы можете не захотеть, чтобы он проверял все преобразования int в короткие; иногда приведение может быть семантически безопасным благодаря гарантиям предварительных условий. По-прежнему существует проблема, является ли num строкой, которую можно преобразовать в int. Если это предполагается, я не вижу проблемы в следовании семантике atoi и простом возврате нуля в случае сбоя преобразования. Итак: int atoshrt(const char*). - person Clifford; 18.01.2021
comment
@Clifford, возвращающий ноль, не информирует вызывающую сторону о том, что значение было недопустимым. Если компилятор встроит код, передающий NULL, это не добавит накладных расходов godbolt.org/z/Pce948 - person 0___________; 18.01.2021
comment
Я знаю; вы упустили мою мысль. Если возврат atoi() приемлем, то допустима и версия рубашки с той же семантикой. Если atoi() не работает, об ошибке не сообщается. Встраивание не устраняет накладные расходы на проверку ошибок, но вы снова упустили мою мысль о том, что в данном случае ими можно пренебречь. - person Clifford; 18.01.2021