Casting covertus numberus?!



  • Is it a cast or is it constructing an integral?

        auto multdigit = [](int64_t x, char y){
            return x * int64_t(y-'0');
        };
    

    The intent is this code it to convert a char to an int64_t type. I have assumed int64_t(<value) is constructing an int64_t. I know in C++ we are supposed to be using the new style casts. So should I really be using a static_cast<int64_t>(<number>) here? Is using the constructor good code anymore?

    I keep searching the web and I find stuff like this, but they are not really covering constructors in these answers.



  • @fcarney said in Casting covertus numberus?!:
    int64_t(y-'0') is creating an int64_t from the parameter, through its constructor. Although similar, it's not a cast, I don't think it's quite the same as either (int64_t)(y - '0') or static_cast<int64_t>(y - '0'), which are casts.



  • @JonB said in Casting covertus numberus?!:

    I don't think it's quite the same

    Yeah, I am going to have to look at the assembly to see what the difference is. I had always assumed when casting integers that it would reserve whatever space was required and fit the number in there. So in that sense I cannot see the difference between a constructor and a cast.



  • @fcarney said in Casting covertus numberus?!:

    it would reserve whatever space was required and fit the number in there

    Don't know what that means. Casting doesn't involve "reserving space".

    One big difference is (I think/presume) casting will never call a constructor. int64_t(something) can do anything it likes in its constructor code. static_cast<int64_t>(something) is more like "this is already acceptable as an int64_t as it is".

    I ought be careful here, because I'm more a C-er than a C++-er, and doubtless I'll say something not quite right...

    LATER EDIT: I think here, and in my previous reply, I have been treating int64_t(something) as the same thing as class(something) , and I don't think that's correct. In the case of something like an int which doesn't have a constructor I think int64_t(something) is the same thing as a cast. So, I wouldn't want all of what I wrote here to quoted on my gravestone :)



  • @fcarney said in Casting covertus numberus?!:

    assembly to see what the difference is

    c++ code:

        int num = 2;
        int64_t num1 = int64_t(num);
        int64_t num2 = (int64_t)num;
        int64_t num3 = static_cast<int64_t>(num);
    

    Well, it looks exactly the same for the integral conversions/casts:

           499 [1]	    int64_t num1 = int64_t(num);
    0x56078aef741f  <+ 7516>        8b 85 2c fc ff ff                 mov    -0x3d4(%rbp),%eax
    0x56078aef7425  <+ 7522>        48 98                             cltq
    0x56078aef7427  <+ 7524>        48 89 85 00 fd ff ff              mov    %rax,-0x300(%rbp)
            500 [1]	    int64_t num2 = (int64_t)num;
    0x56078aef742e  <+ 7531>        8b 85 2c fc ff ff                 mov    -0x3d4(%rbp),%eax
    0x56078aef7434  <+ 7537>        48 98                             cltq
    0x56078aef7436  <+ 7539>        48 89 85 08 fd ff ff              mov    %rax,-0x2f8(%rbp)
            501 [1]	    int64_t num3 = static_cast<int64_t>(num);
    0x56078aef743d  <+ 7546>        8b 85 2c fc ff ff                 mov    -0x3d4(%rbp),%eax
    0x56078aef7443  <+ 7552>        48 98                             cltq
    0x56078aef7445  <+ 7554>        48 89 85 10 fd ff ff              mov   %rax,-0x2f0(%rbp)
    

    The only difference I can see is the mov that loads the value into a different variable location in memory. Which is expected because I used different variables.



  • @fcarney
    This is partly because you're using the example on a simple type (variations of integers) here. If you did this stuff on a class type I think you'd see differences. I'll (try to) keep quiet now.... :)



  • @JonB said in Casting covertus numberus?!:

    I think you'd see differences

    Definitely. My only concern is using it for simple conversions where I just want to say: make this an integer of this type. I use the new style casts for pointers and more complex objects.



  • @JonB said in Casting covertus numberus?!:

    Casting doesn't involve "reserving space".

    I had always assumed that if I cast from a 32 bit integer to a 64 bit integer that the compiler would ensure that the value would now use 64 bits for calculations. At least this is how it has always seemed to operate.



  • @fcarney
    To understand what's different about int64_t(something) vs one of the true casts, i think what you want to Google is static_cast vs functional style cast, e.g. start from https://stackoverflow.com/questions/4474933/what-exactly-is-or-was-the-purpose-of-c-function-style-casts, but there are others.



  • @fcarney said in Casting covertus numberus?!:

    I had always assumed that if I cast from a 32 bit integer to a 64 bit integer that the compiler would ensure that the value would now use 64 bits for calculations. At least this is how it has always seemed to operate.

    Yes that is indeed right. I didn't think of that as "reserving space". It's variables for which "space is reserved", and that's not affected by any casting or not, which is what I thought you were referring to. Mis-interpretation.



  • @fcarney
    BTW, reading around (and then I must get back to my work!), it seems there is another C++ variant to int64_t(something) which is actually supposedly preferred (to just that one): int64_t{something}!

    From what I read, the consensus is best to use the static_cast<> family of casts for all of this. The basic claim is that it makes it easier to search source code for these.


Log in to reply