2016-10-08 13 views
-1

У меня есть следующая программа.Почему printf показывает неправильное значение для переменной int для разных настроек компилятора 64 против 32?

int main() { 
    int a = 1; 
    long long b = 100000000; 
    printf("size of a is: %d \t sizeof b is:%d \n",sizeof(a),sizeof(b)); 
    printf("a= %d b=%d a=%d \n", a, b, a); 
    printf("a= %d b=%Ld a=%d \n", a, b, a); 
    b = 10000000000; 
    printf("a= %d b=%d a=%d \n", a, b, a); 
    printf("a= %d b=%Ld a=%d \n", a, b, a); 
} 

Когда я скомпилировать его с gcc -m32 выходом

size of a is: 4  sizeof b is:8 
a= 1 b=100000000 a=0 
a= 1 b=100000000 a=1 
a= 1 b=1410065408 a=2 
a= 1 b=10000000000 a=1 

, но при компиляции с gcc -m64 выходом.

size of a is: 4  sizeof b is:8 
a= 1 b=100000000 a=1 
a= 1 b=100000000 a=1 
a= 1 b=1410065408 a=1 
a= 1 b=10000000000 a=1 

Почему это показывает неправильные значения во время печати третьего аргумента PRINTF (а)?

Мой GCC версии

[email protected]:~$ gcc -v 
Using built-in specs. 
COLLECT_GCC=gcc 
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper 
Target: x86_64-linux-gnu 
+2

Неопределенное поведение для вызова printf с идентификатором формата, который не соответствует типу. Таким образом, вывод printf не гарантируется. Если вы неправильно используете% d для печати b, то вывод printfs не определен. Включите предупреждения компилятора и исправьте спецификаторы формата.Тот факт, что он работает на 64-битной основе, - это просто удача от реализации. –

+0

@SectoKia ok, но почему значение 'a' изменяется (от первого аргумента до третьего) в 32-битном компиляторе? – priyanka

+0

@priyanka Я бы не сказал, что значение 'a' изменилось. Случилось так, что printf запутался и не напечатал значение 'a' должным образом. Это запуталось, потому что ты солгал ему. –

ответ

3

Вы должны напечатать long long значения, используя %lld. Вы не можете распечатать их, используя %d. Если вы попытаетесь распечатать их с помощью %d, это не сработает. (Оказывается, %Ld не прав, хотя это звучит так, как будто gcc позволяет вам уйти от него.)

Для номера 10000000000 требуется 34 бита. Как вы обнаружили, он не будет вписываться в 16-битную или 32-разрядную версию int. Однако он будет вписываться в 64-битный long long int.

Трудно точно узнать, что происходит, когда вы пытаетесь распечатать 64-разрядный long long с использованием %d. Вы можете представить, что 8 байт попадают в стек, а %d выталкивает 4 из них. Таким образом, остальные четыре все еще остаются в стеке, так что это то, что выталкивается для третьего %d, а не a. Это не обязательно то, что происходит, на самом деле это может быть более сложным. И осложнения могут очень легко зависеть от того, компилируете ли вы в режиме 32 или 64 бит.


Это заканчивает тем, что маленькая, простая иллюстрация важного момента: когда программа использует неопределенное поведение, потенциально всех аспектов программы становятся неопределенными. Когда вы делаете что-то действительно не так, например, пытаетесь напечатать значение blong long, используя %d, что не так, это не только то, что значение b напечатано неправильно, но и все пошло не так.

Вот аналогия. Предположим, вы покупаете новый спортивный велосипед с тонкой, быстрой шиной. Продавец напоминает вам, что это дорожный велосипед, для езды по ровным асфальтированным дорогам. Если вы попытаетесь покататься на нем внедорожника, продавец предупреждает вас, шины, скорее всего, появятся, если вы попадете в скалу.

Теперь предположим, что вы do ездить на велосипеде с дороги. И предположим, что вы переходите через скалу, и шина выскакивает, и из-за этого вы теряете контроль и крушась, и сгибаете руль, а также получаете разрез на лоб. Предположим, вы вернулись в магазин велосипедов и сказали: «Хорошо, я поехал на велосипеде с дороги, и шина выскочила, как вы сказали. Но можете ли вы объяснить, почему рули согнуты, и я получил это сокращение на моей голове?»

+0

Проблема ОП запрашивает не с 'b', а с' a', равным 2, когда используется 32-битная опция. – AntonH

+0

@AntonH да, а также почему это 0 в случае первого printf. – priyanka

+0

@AntonH Правильно, хотя реальный ответ заключается в том, что так работает неопределенное поведение: существует несоответствие между типом 'b' и спецификатором формата printf, используемым для его печати, и это несоответствие распространяется на другие части программы, включая как печатается 'a'. Но я обновил свой ответ. –