2016-04-19 10 views
0

У меня есть следующий фрагмент кода:C итерация до очень большого числа - предупреждение компилятора о неподписанных INT

#include <stdio.h> 
#define POWER 10000000000000000000 

int main() 
{ 
    int i; 
    for (i = 0; i < POWER; i++) 
    { 
     .... 
    } 
    return 0; 
} 

и компилятор дает мне следующие предупреждения:

EX1. c: 33: 19: warning: целочисленная константа настолько велика, что она неподписанна [включена по умолчанию] ex1.c: 33: 2: предупреждение: эта десятичная константа не имеет знака только в ISO C90 [включена по умолчанию]

Как я могу повторить с i, пробегая все значения, пока не достигнет POWER? Я пробовал объявить i как unsigned int, но предупреждения остаются.

+1

вы действительно хотите, чтобы петли '10000000000000000000' раз? 'for (long i = 0;; i ++)' будет, технически, делать то же самое (бесконечный цикл) –

+0

@DmitryBychenko Я пытаюсь выполнить итерацию по очень большим числам, так что да, мне нужно так много циклов. – Marievi

+3

'#define POWER 10000000000000000000' - >>' #define POWER 10000000000000000000ULL' и 'int i;' - >> 'unsigned long long i;' – joop

ответ

4

Для вашей постоянной константы 10000000000000000000 требуется 64 бит. В шестнадцатеричном виде это 0x8ac7230489e80000. Он может быть представлен в неподписанным 64-разрядным типом, но не в подписанном 64-разрядным типом.

С C99 все целочисленные константы имеют некоторый тип подписи: первый из int, long int или long long int, в котором значение будет соответствовать.

C90 (у которого еще не было long long int) были разные правила. В C90 неопределенная целочисленная постоянная константы имеет тип int, long int или unsigned long int.

Режим gcc по умолчанию - -std=gnu90, который поддерживает стандарт C90, а также расширения для GNU. Если вы используете 64-битную систему, то long и unsigned long - 64 бит. В соответствии с правилами C90 ваша константа имеет тип unsigned long (предполагается, что unsigned long составляет не менее 64 бит). В соответствии с правилами C99 и более поздних версий, предполагая, что целочисленный тип не превышает 64 бит, это нарушение ограничений. (версия gcc версии 5 изменила значение по умолчанию на -std=gnu11.)

Компилятор, который, по-видимому, работает в соответствии с правилами C90, предупреждает вас о том, что значение 10000000000000000000 отличается в зависимости от того, какая версия стандарта используется компилятором.

Вы можете сделать свою программу «работы» со следующими изменениями:

#define POWER 10000000000000000000ULL // suffix to specify the type 
... 
for (unsigned long long = 0; i < POWER; i ++) 
... 

Но хотя это делает программу действительно, это не делает его практичным.На одной итерации за наносекунду для завершения цикла потребуется более 3 столетий. Мой собственный разумно современный компьютер выполняет одну итерацию пустойfor цикл около 1,6 наносекунды. Какую бы проблему вы ни пытались решить, я предлагаю либо найти другой способ ее решения, либо уменьшить ее до меньшей проблемы. Самый быстрый способ выполнить этот цикл - подождать несколько десятилетий, чтобы оборудование стало быстрее, и затем скомпилировать и выполнить его.

(Это предполагает, что тело цикла является нетривиальным. Если тело цикла не делает ничего, компилятор может оптимизировать на цикл в целом.)

+0

«В правилах C90 ваша константа имеет тип unsigned long». Вы в этом уверены? В C++ десятичный литерал никогда не преобразуется в неподписанный тип. Я не совсем уверен в C, хотя. – Bathsheba

+0

@ Батшеба: Да, я уверен. Я только что проверил свою копию стандарта C90 (ISO/IEC 9899: 1990 (E)). –

+0

В этом случае имейте upvote! – Bathsheba

-1

Значение 10000000000000000000 (= 10^19, если я правильно подсчитал) требуется 64 бита для выделения, это 8 байт. Вы получаете предупреждение, потому что тип int использует 4 байта, и поэтому он не может сохранить это число. С unsigned int вы удваиваете максимальное положительное число, которое вы можете сохранить, но это 4 294 967 295, которого все еще недостаточно. Если вы хотите использовать int, вы можете использовать итерационные циклы.

for(i=0;i<p;i++){ 
     for(j=0;j<p;j++){ 
      for(k=0<p;k++){ 
      /*loop*/ 
      } 
     } 
    } 

где р был бы int или unsigned int с vaue кубического корня мощности (в данном случае кубического корень не действует, как 19% 3! = 0 и р не был бы int, его больше идеи, чем фактическое решение)

+0

«Вы получаете предупреждение, потому что тип' int' использует 4 байта, и поэтому он не может сохранить это число »-> Нет. Предупреждение происходит, потому что' 10000000000000000000' не может вписаться в 'long long'. (C99) или в 'unsigned long' (C90). Диапазон 'int' не является проблемой. – chux