присвоение значения длинным длинным целым, используя gcc на sparc solaris - PullRequest
1 голос
/ 27 февраля 2012

Я наткнулся на то, что мне кажется довольно странным.Тестовая программа

int main(int argc, char* argv[])
{
    cout<<"hello"<<endl;
    long unsigned l = 0x12345678;
    long long unsigned ll =  0x12345678;
    cout<<sizeof(l)<<endl;
    cout<<sizeof(ll)<<endl;
};

вывод:

hello    
4    
8

Никаких сюрпризов.long int имеет размер 4 байта, а long long имеет размер 8 байтов.Однако, когда я изменяю его так, что long long назначается

long long unsigned ll =  0x123456789;

во время компиляции, я получаю

error: integer constant is too large for "long" type

Теперь этот же тест выполняет компиляцию , если явызвать 64-битную сборку, используя опцию -m64.Я что-то не так делаю или это ошибка в GCC?

Ответы [ 2 ]

6 голосов
/ 27 февраля 2012

Измените его на

long long unsigned ll = 0x123456789ULL; // notice the suffix

Без суффикса литерал больше максимального значения unsigned long на вашем компьютере, и это, согласно C ++ 03 (но не C ++ 11, который имеет long long), является неопределенным поведением.Это означает, что может произойти все что угодно, включая ошибку во время компиляции.

Также ничего не стоит, что в C ++ 03 нет long long, так что работа не гарантируется, вы полагаетесь на расширение,Вам, вероятно, лучше использовать C ++ 11.

3 голосов
/ 27 февраля 2012

Дело в том, что многие люди, похоже, смотрят на строку кода, подобную вашей:

unsigned long long ll = 0x123456789;   /* ANTI-PATTERN! Don't do this! */

и причине "о, тип unsigned long long, поэтому значение равно unsigned long long иэто назначается ", но это просто не так, как работает С.Литералы имеют свой собственный тип , который не зависит от контекста, в котором они используются.И тип целочисленных литералов: int.

Это то же заблуждение, что и у людей:

const double one_third = 1 / 3;   /* ANTI-PATTERN! Don't do this! */

Думая "тип слева - double, так чтоследует назначить 0.3333333 ... ".Это просто (снова!) Не так, как работает С.Типы разделяемых литералов по-прежнему int, поэтому правая часть вычисляется точно в 0, что затем преобразуется в double и сохраняется в переменной one_third.

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

...