1

I have a piece of code:
Under Windows MSVC 2012

#include <stdio.h>
#include <string.h>


namespace myname{
    double var = 42;
}

extern "C" double _ZN6myname3varE = 10.0;

int main(){
    printf("%d\n", _ZN6myname3varE);

    return 0;
}

The output is 0. But I think the output should be 10. Could you help explain why?

Zachary
  • 1,633
  • 2
  • 22
  • 34
  • 6
    `d` -> `f` .... – Mysticial Jul 17 '13 at 03:49
  • 1
    I'm not sure *what* you wanted that to be, but it's a [reserved identifier](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier) – chris Jul 17 '13 at 03:50
  • 2
    Voting to put on hold as the problem described is caused by a simple misunderstanding (%d instead of %f). – jogojapan Jul 17 '13 at 03:52
  • @Mysticial What do you mean? Do you printf will convert int to double/float? – Zachary Jul 17 '13 at 03:53
  • @Mysticial I know your meaning. But I want to know why 0 is output? How this happen? – Zachary Jul 17 '13 at 03:56
  • 1
    %d says: grab four bytes off the stack, treat them as an int, print the decimal representation of that int. You pass a double to the function; the compiler pushes 8 bytes representing that double onto the stack. It just so happens that four low-order bytes of the binary representation of the double value 10.0 are all zeros. – Igor Tandetnik Jul 17 '13 at 04:06
  • @IgorTandetnik I thought the printf will convert double argument to int (10.0 to 10), and then will output the converted argument. Why printf does not convert argument but just grad the lower 4 bytes? – Zachary Jul 17 '13 at 04:09
  • @Zack, It's officially undefined behaviour. `printf` has no knowledge of the type of variable you pass in other than what you tell it. `std::cout` is better for that. – chris Jul 17 '13 at 04:10
  • @chris When the function argument type is not the same as parameter type, undefined behaviour happens? It seems that compile will help convert the arguments to desired type of parameter. – Zachary Jul 17 '13 at 04:13
  • @Zack, Read about how C variadic arguments work. You have to literally put the type, e.g., `int`, that is the next in the list. How does it know which is next in the list? You tell it with the format specifiers. If you say it's an `int`, it will try to pull an `int`, when it's really a `double`. There is no way for the compiler to know what the next one's supposed to be. Variadic templates do the same in C++11, but are type safe. – chris Jul 17 '13 at 04:19
  • 1
    @Zack: Compiler do not parse and find the kind of datatypes we have given inside the `printf`'s `char* format`. It happens in runtime only. – raj raj Jul 17 '13 at 04:21
  • This is the danger of preferring a C solution to a C++ solution. This wouldn't have happened with `cout`. `printf` is unable to do type checking. – Mark Ransom Aug 16 '13 at 17:30

2 Answers2

2

Answer for "But I want to know why 0 is output? How this happen?".

double is 64-bit and int is 32-bit. When double is truncated to int (because of using %d), only first 4 bytes stored in the memory location of double is taken into the int value.

Here, value of double _ZN6myname3varE is 10.0, which is 0x4024000000000000 in hex and stored as 00000000 00002440 in memory (little endian). So, when truncated to int, only 4 byte LSB is taken which is obviously zero.

raj raj
  • 1,932
  • 1
  • 14
  • 15
0
printf("%d\n", _ZN6myname3varE);

%d should be changed to %f, which prints type double

But there's another problem: name mangling. When I tested the program in gcc, it shows an error:

Error: symbol `_ZN6myname3varE' is already defined

The problem is the name _ZN6myname3varE is a reserved identifier in C++ because it begins with underscore and an uppercase letter.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294