printf scanf %d - нули для всех кроме последнего - как исправить - несколько значений подряд
Primary tabs
Forums:
Почему если вводить три единицы - для двух первых значений будут напечатаны нули??
#include < stdio.h > char main (void) { char banana=1; char choc=1; char apple=1; printf("How many bananas do you need?\r\n"); scanf(" %d",&banana); printf("How many bars of chocolate do you need?\r\n"); scanf(" %d",&choc); printf("How many apples do you need?\r\n"); scanf(" %d",&apple); printf("Total:\r\n"); printf("%-15s: %d\r\n","Bananas",banana); printf("%-15s: %d\r\n","Choc.Bars",choc); printf("%-15s: %d\r\n","Apples",apple); return; }
То есть что-то типа:
How many bananas do you need? How many bars of chocolate do you need? How many apples do you need? Total: Bananas : 0 Choc.Bars : 0 Apples : 1
- Log in to post comments
- 7844 reads
math2
Sat, 07/18/2015 - 00:48
Permalink
Если компилировать эту
Если компилировать эту программу компилятором
cc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
то такого эффекта не наблюдается. Однако при этом cc выдаёт следующие предупреждения
Но если компилировать эту программу более старым компилятором
cc 2.95.4,
то для первых двух переменных будут печататься нули. Почему?
Посмотрим по каким адресам загружаются переменные
Используем для этого отладчим gdb
Строки 32, 34 и 36 показывают, что наши переменные размещаются в памяти последовательно:
В машинах архитектуры x86 младший байт целочисленных типов
(например, 32 разрядные int в си, или dword в ассемблере) размещается по младшему адресу.
Адрес переменной в Си есть адрес её младшего байта.
Переменная типа char занимает в памяти один байт, а переменная типа int занимает 4 байта.
%d указывает на тип int, то есть на 4 байта.
Если будет выполнена строка
scanf(" %d",&banana);
то в память начиная с адреса 0xbffff6f7, будут записаны 4 байта.
Это значит, что будут изменены ячейки по адресам
После выполнения строки
в память, начиная с адреса 0xbffff6f6, будут записаны 4 байта.
Это значит, что будут изменены ячейки по адресам
Получается, что если мы будем вводить, например 12, то младший байт того значения типа int,
которое будет записываться начиная с адреса 0xbffff6f6 (это адрес переменной banana),
будет содержать значение 12, а старшие три байта --- нули.
Поэтому теперь байт по адресу &banana имеет значение ноль.
После выполнения строки
scanf(" %d",&apple);
в память, начиная с адреса 0xbffff6f5, будут записаны 4 байта.
Это значит, что будут изменены ячейки по адресам
0xbffff6f9
0xbffff6f8
0xbffff6f7
0xbffff6f6
Получается, что мы уничтожаем и значение переменной choc.
Тем не менее, когда будет выполняться строка
будет выводиться значение именно одного байта по адресу &apple.
В обоих системах, и в старой с компилятором cc 2.95.4, и в новой с cc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4, это значение, кажется, будет интерпретировано как дополнительный код.
Так как когда я ввожу для apple значение 128, то получаю в младшем байте
1000 0000,
а программа выводит минус 128. Это очень похоже на дополнительный код.
Кстати, компилятор cc 2.95.4 выдаёт ещё такое предупреждение:
vedro-compota
Sat, 07/18/2015 - 10:08
Permalink
классный ответ)
классный ответ)
_____________
матфак вгу и остальная классика =)
math2
Sat, 07/18/2015 - 00:49
Permalink
Нужно изменить тип переменных
Нужно изменить тип переменных с char на int.