2016-01-17 2 views
-5

Я хотел знать, почему вывод этого кода равен 0? y.beta и p->beta - одна и та же переменная, так что выход не должен быть 3?Почему различные спецификаторы формата дают разные выходные данные с помощью printf?

int main() { 
    struct MyType { 
     int alpha; 
     double beta; 
    }; 
    static struct MyType y; 
    struct MyType *p = &y; 
    y.alpha = 1; 
    p->alpha = 2; 
    p->beta = 2.5; 
    y.beta = 1.5; 
    printf("%d", y.beta + p->beta); 
    return 0; 
} 
+1

Параметр '% d' должен быть'% f' – user3386109

+0

спасибо, почему не% d работает? @ user3386109 – Noooor

+0

@Nona:% d для цифр (целые числа),% f для поплавков. – user3813674

ответ

1

Вы вызвать неопределенное поведение, передавая неправильный тип аргумента printf:

printf("%d", y.beta + p->beta); 

%d ожидает int будет принят, y.beta + p->beta это значение double.

Изменить код:

printf("%f\n", y.beta + p->beta); 

Неопределенное поведение означает, что все может случиться; тщетно пытаться понять, почему он печатает 0. Что-то еще может произойти на другой машине, или в другое время, или даже если идет дождь или если босс приходит ;-)

1

Как chqrlie правильно указал, printf("%d", somevariable) ожидает, что переменная передается как int , тогда как ваш результат - значение типа double.

%d называется спецификатором формата. Они необходимы, потому что разные типы данных передаются и интерпретируются разными способами процессором, возможно, в другом месте в памяти или в разных регистрах (как в случае платформы x86_64). Таким образом, даже одно и то же место памяти с одним и тем же битовым шаблоном может интерпретироваться по-разному на основе типа данных. Это то, что происходит в этом другом примере:

int main() { 
    int a = 1048577;; 
    printf("%d\n", a); 
    printf("%hd", a); //hd is the format specifier for short int 
    return 0; 
} 

выход:

1048577 
1 

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

Почему это так? Это двоичное представление 1048577 (предполагая, что 32-битный int):

00000000 00010000 00000000 00000001 

Если формат спецификатор short int (%hd), то это шорты 16 бит в ширину, только 16 младших бит порядка от значения , поэтому выход равен 1.

Нечто подобное может происходить в вашем случае на некоторых архитектурах (x86 32 бит) или что-то хуже других те, где передается значение double по-другому и printf получает int от места, где ничего конкретного не была написана вызывающий и любое случайное значение могут быть там, например 0.

Решение этой проблемы было бы изменить код, чтобы printf("%f", y.beta + p->beta); как указал chqrlie

+0

Благодарим вас за дополнительные объяснения, но ваш пример несколько вводит в заблуждение: '% hu' ожидает' unsigned int', но интерпретирует его как un 'unsigned short'. Это не вызовет неопределенное поведение, тогда как '% llu' будет на платформах, где' sizeof (long long)! = Sizeof (int) '. – chqrlie

+0

Исправлено:% hd. Теперь все в порядке. – nilanjanaLodh

+0

не полностью. '% hd' и'% hu' оба переинтерпретируют аргумент 'int' или' unsigned int', как он, накладывая его соответственно на 'short' и' unsigned short'. В вашем объяснении вы указываете * последние 8 бит *, но это действительно * последние 16 бит * или, возможно, больше в зависимости от фактического размера «короткого». Кроме того, различные типы могут передаваться в разных местах в 'printf', поэтому обсуждение того, как интерпретируются битовые шаблоны, может быть нецелесообразным. Я исправил ваш ответ. – chqrlie