Debugging floating point representation in C vs C ++ (CLI)

A bit of background . I worked on some data conversion from Cto C#using C++/CLImidlayer, and I noticed a peculiarity in the way the debugger shows floatsand doubles, depending on which DLL the code is executing (see code and images below). At first I thought that this was due to controlled / unmanaged differences, but then I realized that if I completely left the layer C#and used only unmanaged data types, the same behavior was shown.

Test case . To continue exploring the problem, I created an isolated test case to clearly identify strange behavior. I assume that anyone who can test this code already has a working solution and dllimport/ dllexport/ macros installed . My called DLL_EXPORT. If you need a minimal working header file let me know. Here the main application is located in Cand calls the function from the dll C++/CLI. I am using Visual Studio 2015 , and both assemblies 32 bit.

I'm a little worried, as I'm not sure if this is what I need to worry about, or what the debugger is doing (I'm leaning toward the latter). And frankly, I'm just frank about what is happening here.

Question: Can someone explain the observed behavior, or at least point me in the right direction?

C - Call Function

void floatTest()
{
    float floatValC = 42.42f;
    double doubleValC = 42.42;
    //even if passing the address, behaviour is same as all others.
    float retFloat = 42.42f;
    double retDouble = 42.42;
    int sizeOfFloatC = sizeof(float);
    int sizeOfDoubleC = sizeof(double);

    floatTestCPP(floatValC, doubleValC, &retFloat, &retDouble);

    //do some dummy math to make compiler happy (i.e. no unsused variable warnings)
    sizeOfFloatC = sizeOfFloatC + sizeOfDoubleC;//break point here
}

C ++ / CLI Header

DLL_EXPORT void floatTestCPP(float floatVal, double doubleVal, 
      float *floatRet, double *doubleRet);

C ++ / CLI Source

//as you can see, there are no managed types in this function
void floatTestCPP(float floatVal, double doubleVal, float *floatRet, double *doubleRet)
{
    float floatLocal = floatVal;
    double doubleLocal = doubleVal;

    int sizeOfFloatCPP = sizeof(float);
    int sizeOfDoubleCPP = sizeof(double);

    *floatRet = 42.42f;
    *doubleRet = 42.42;

    //do some dummy math to make compiler happy (no warnings)
    floatLocal = (float)doubleLocal;//break point here
    sizeOfDoubleCPP = sizeOfFloatCPP;
}

Debugger in C - breakpoint on last linefloatTest()

Debugger in C ++ / CLI - breakpoint from second to last linefloatTestCPP()

+3
source share
1 answer

Consider a Debugger in C ++ / CLI is not necessarily encoded in C, C # or C ++.

MS libraries support the "R" format : a string that can round to the same number. I suspect that this format was used or g.

Without MS source code, the following assumption is a good assumption:

, double double.. "42.420000000000002", "42.42" - .

42.42 IEEE double 42.4200000000000017053025658242404460906982..., , , .

; C

int main(void) {
  puts("12.34567890123456");
  double d = 42.42;
  printf("%.16g\n", nextafter(d,0));
  printf("%.16g\n", d);
  printf("%.17g\n", d);
  printf("%.16g\n", nextafter(d,2*d));
  d = 1 / 3.0f;
  printf("%.9g\n", nextafterf(d,0));
  printf("%.9g\n", d);
  printf("%.9g\n", nextafterf(d,2*d));
  d = 1 / 3.0f;
  printf("%.16g\n", nextafter(d,0));
  printf("%.16g\n", d);
  printf("%.16g\n", nextafter(d,2*d));
}

12.34567890123456
42.41999999999999
42.42
42.420000000000002   // this level of precision not needed.
42.42000000000001
0.333333313
0.333333343
0.333333373
0.3333333432674407
0.3333333432674408
0.3333333432674409

double double "" , . f .

+1

Source: https://habr.com/ru/post/1691193/


All Articles