6.16 — Explicit type conversion (casting) and static_cast

In the previous lesson 6.15 -- Implicit type conversion (coercion), we discussed that the compiler can implicitly convert a value from one data type to another through a system called implicit type conversion. When you want to promote a value from one data type to a larger similar data type, using implicit type conversion is fine.

However, many new programmers try something like this: float f = 10 / 4;. However, because 10 and 4 are both integers, no promotion takes place. Integer division is performed on 10 / 4, resulting in the value of 2, which is then implicitly converted to 2.0 and assigned to variable f!

In the case where you are using literal values (such as 10, or 4), replacing one or both of the integer literal values with a floating point literal value (10.0 or 4.0) will cause both operands to be converted to floating point values, and the division will be done using floating point math (and thus retain the fractional component).

But what if you are using variables? Consider this case:

Variable f will end up with the value of 2. How do we tell the compiler that we want to use floating point division instead of integer division? The answer is by using a type casting operator (more commonly called a cast) to tell the compiler to do explicit type conversion. A cast represents a request by the programmer to do an explicit type conversion.

Type casting

In C++, there are 5 different types of casts: C-style casts, static casts, const casts, dynamic casts, and reinterpret casts. The latter four are sometimes referred to as named casts.

We’ll cover C-style casts and static casts in this lesson. Dynamic casts we’ll save until after we cover pointers and inheritance in future lessons.

Const casts and reinterpret casts should generally be avoided because they are only useful in rare cases and can be harmful if used incorrectly.


Avoid const casts and reinterpret casts unless you have a very good reason to use them.

C-style casts

In standard C programming, casts are done via the () operator, with the name of the type to convert the value to placed inside the parenthesis. For example:

In the above program, we use a float C-style cast to tell the compiler to convert i1 to a floating point value. Because the left operand of operator/ now evaluates to a floating point value, the right operator will be converted to a floating point value as well, and the division will be done using floating point division instead of integer division!

C++ will also let you use a C-style cast with a more function-call like syntax:

This performs identically to the prior example.

Although a C-style cast appears to be a single cast, it can actually perform a variety of different conversions depending on context. This can include a static cast, a const cast or a reinterpret cast (the latter two of which we mentioned above you should avoid). As a result, C-style casts are at risk for being inadvertently misused, and not producing the expected behavior, something which is easily avoidable by using the C++ casts instead.

As an aside...

If you’re curious, this article has more information on how C-style casts actually work.


Avoid using C-style casts.


C++ introduces a casting operator called static_cast, which can be used to convert a value of one type to a value of another type.

You’ve previously seen static_cast used to convert a char into an int so that std::cout prints it as an integer instead of a char:

The static_cast operator takes a single value as input, and outputs the same value converted to the type specified inside the angled brackets. Static_cast is best used to convert one fundamental type into another.

The main advantage of static_cast is that it provides compile-time type checking, making it harder to make an inadvertent error. Static_cast is also (intentionally) less powerful than C-style casts, so you can’t inadvertently remove const or do other things you may not have intended to do.

Best practice

Favor static_cast when you need to convert a value from one type to another type

Using casts to make implicit type conversions clear

Compilers will often complain when an unsafe implicit type conversion is performed. For example, consider the following program:

Casting an int (4 bytes) to a char (1 byte) is potentially unsafe (as the compiler can’t tell whether the integer will overflow the range of the char or not), and so the compiler will typically print a warning. If we used list initialization, the compiler would yield an error.

To get around this, we can use a static cast to explicitly convert our integer to a char:

When we do this, we’re explicitly telling the compiler that this conversion is intended, and we accept responsibility for the consequences (e.g. overflowing the range of a char if that happens). Since the output of this static_cast is of type char, the assignment to variable ch doesn’t generate any type mismatches, and hence no warnings.

In the following program, the compiler will typically complain that converting a double to an int may result in loss of data:

To tell the compiler that we explicitly mean to do this:

Quiz time

Question #1

What’s the difference between implicit and explicit type conversion?

Show Solution

6.17 -- Unnamed and inline namespaces
6.15 -- Implicit type conversion (coercion)

127 comments to 6.16 — Explicit type conversion (casting) and static_cast

  • Benur21

    Is it ok to use

    to truncate floats?

  • Diana

    Why does the following code give me an int instead of float?

    • You're printing @i. @i is an int.

      • Diana

        Thanks. I know there is something wrong with my reasoning but first of all, i/3.0 is an arithmetic expression between an integer i and a float 3.0. The compiler will convert int to float since float is a higher priority operand and the result should be a float. Secondly, even if the result of the dividing is still an int, using static_cast<float> will convert it to a float and equal the result to i. Where did I got wrong?

  • Rai

    I saw a human development calculator here and I thought I'd give it a try. Is there anything I can improve on?




    • Hi Rai!

      * Initialize your variables with uniform initialization
      * @getLifeExpectancy, @getMeanEducationIndex and @getExpectedEducationIndex are equivalent except for the message. Don't repeat code.
      * @FractionalPart doesn't follow your naming convention
      * @FractionalPart is declared to return a double, but returns a bool and is used as if it returned a bool.
      * Use double literals when calculating with doubles.
      * Use @std::log and @std::cbrt instead of their non-namespaced counterparts. Remove the include to @<math.h>

      • Rai

        1. Is it preferred to use uniform initialization? I find it harder to read and I get errors in my compiler when I use it

        3. like this?

        4. like this?

        Thanks for the help.

        • 1.
          Yes. I prevents unnecessary copies an can be used everywhere.
          If you get errors, you're either using it wrong or using wrong types. Uniform initialization intentionally causes errors when you try to initialize a variable with the wrong type (whereas copy/direct initialization would perform an implicit cast, which is potentially unwanted).

          Yes. It still violates your naming convention though. All your other functions start with a lower case letter.

          Yes. @HumanDevelopmentIndex also has a capital leading letter. Line 3 is inconsistently formatted. Use the auto-formatting feature of your editor (a - b vs a-b).

  • jg

    In the "C-style casts" paragraph, the 2 code examples look exactly the same:

    In standard C programming, casts are done via the () operator, with the name of the type to cast to inside.

    C++ will also let you use a C-style cast with a more function-call like syntax:

    Is there a typo ?

  • Sri

    Hello Alex, I am kind of confused, as even after I use the type casting to my project, the value still returns 0 in the end, although I wish it to be a decimal in between 0 and 1. Is there anything I can do?

    the answer turns out to be this:

    What is the life expectancy of this country? 44
    What is the mean years of schooling? 3
    What is the expected years of schooling? 4
    What is the GDP per capita of this country? 4
    1The human development of this country is 0

    and the human development stays as such no matter what I do :<

    • Alex

      Yes, you can actually call the functions you wrote to do the calculations.

      So you define a new variable called humanDevScore, which is uninitialized. Then you print the value of that uninitialized variable. Then you return that uninitialized value back to the OS. You probably meant to initialize humanDevScore with the return value from humanDevelopmentIndex(), but you never did.

      • RJ

        I know this is an old post but I have a question about line 14 and those similar to it. Is it really necessary to use the static cast when the parameters are already doubles to begin with?

        . My understanding is that the double lifeExpectancy would be converted to a double even though it's all ready a double. Am I right about this?

        • Alex

          It's not necessary to use static_cast to get floating point division in the case where one of the parameters is a non-integer.

          > My understanding is that the double lifeExpectancy would be converted to a double even though it's all ready a double. Am I right about this?


  • Kushagra

    Why c style cast is avoided?
    please explain it

    • Alex

      The C-style cast is dangerous because it can perform different kinds of casts depending on context (making it unclear what you're actually getting), and it doesn't make the programmer's intention very clear.

      C++ casts are clearer and safer.

  • I have a question.
    lets say;
    char c='a';
    now we apply static_cast<int>(c) to c so as to convert it into an integer type value.
    so, as now c is an integer. Can we apply arithmetic operations to it?
    if yes, then why doesn't this code worked?

    using namespace std;
    int main()
    char c='a';

    • Alex

      c=static_cast(c); is redundant -- you're converting a char to an int, and then assigning it back to a char variable (undoing your conversion).
      c*=2 works just fine (it multiplies the variables value by 2), but you're still outputting a char.

      static_cast doesn't change the type of a variable -- it changes the type of a value.

  • Taksh

    Hey Alex,
    I gave the wrong example of code in my last comment. I meant that when you wrote:

    In the following program, the compiler will typically complain that converting a double to an int may result in loss of data:

    You already defined i as an int, however you said that you were converting a double into an int

  • Taksh

    Dear Alex,

    In this lesson, you wrote:

    Casting an int (4 bytes) to a char (1 byte) is potentially unsafe, and the compiler will typically complain. In order to announce to the compiler that you are explicitly doing something you recognize is potentially unsafe (but want to do anyway), you can use a cast:

    However, i already an int (you are not converting a double into an int).

    • Alex

      I'm not sure I understand your point. Any time you do a narrowing conversion your compiler should give you a warning, and you should use a static_cast to make your intention clear. int to char is definitely narrowing.

  • Bernat

    Hi Alex,
    about the code in the static cast paragraph, when you do char c = 97, char can only hold one character right? Did you mean 'a' and then when you do the static cast it appears as 97?
    Sorry if I'm wrong, I don't really know.

    • Bernat

      Oh, I've just realized that 97 it's not a character because it doesn't have the ' '. Sorry for not seeing it before.

    • Alex

      I updated the example to use 'a' instead of 97 (even though they're identical), because I think it's more intuitive that way.

      Chars can only hold one character. When you assign a char integer value 97, you're assigning it the single character 'a', because character 'a' has integer value 97.

  • James Ray

    "Because C-style casts are not checked by the compiler at compile time, C-style casts can be inherently misused, because they will let you do things that may not make sense, such as getting rid of a const or changing a data type without changing the underlying representation (leading to garbage results)." It may be helpful to give examples in code of each of these situations.

  • Trey

    Alex, this does nothing about this lesson but can you make a suggestion to make this code work:

  • Matt

    In section "static_cast", 2nd sentence, "you're" should be "you've".

  • Richard

    C-style casts

    In standard C programming, casts are done via the () operator, with the name of the type to cast to inside. For example:

    int i1 = 10;
    int i2 = 4;
    float f = (float)i1 / i2;
    In the above program, we use a float cast to tell the compiler to promote i1 to a floating point value. Because i1 is a floating point value, i2 will then be promoted to a floating point value ...

    I believe in the last sentence, it should be "converterd" instead of "promoted" as one variable is an integer type value, and the other one is a floating point values. Is my understanding correct?

  • reznov

    In physics we often use 'variable' constants like gravity. Is it possible to write a program that can overwrite a constant like gravity using C-conversion and lock it back in again?

    i.e. I ask the user to specify his/her country, a case diagram will link the specific gravity to that country and overwrite the current 'const g_gravity' and locks it back in so nothing else can touch it.

    That would be lovely for us physicists :)

    • Alex

      Nope. Generally it's a bad idea to cast away const unless you know the object was created non-const -- the compiler will make a lot of optimizations for const objects, and if you try to make them non-const, undefined behavior will result. So if you want something that changes values (even once), you'll have to make it non-const.

      But that's not such a bad thing. You can encapsulate your gravity variable so it can't be touched directly (either by making it static in a file and providing functions to modify/set it, or putting it in a class as a private member and adding member functions to modify/set it).

  • Byron

    Hello there,

    Can you please explain how, in the last example (i = 1/2.5) data will be lost?
    i = 100, so 100 / 2.5 would be 40, which is an integer.
    Do you mean that the compiler will recognise that dividing with 2.5 (float/double) may lead to a result with non-zero decimals and that, when converted back to int (since i is int), the decimals will be lost?

    • Alex

      Yes, that's exactly what it means. In this case, since 2.5 can be represented precisely, and 100 / 2.5 leads to an integer, there's no precision lost. But in many cases, the result of a division containing a float won't be an integer -- so most compilers will complain in general about any implicit conversion from a floating point type to an integer type. Even in the cases where the result should be an integer, precision issues may lead to the wrong result. Hypothetically, if 2.5 ended up getting represented as 2.5000001, then 100/2.5000001 could end up as 39.9999998, which would get truncated to integer 39.

  • Sushant

    Hi Alex,
    Are you planning to add other cpp casting too. It would be great if you could cover RTTL too.

    Thanks for creating such a great cpp learning resource with clear and concise examples.


    • Alex

      RTTL is just dynamic casts and typeid -- I already covered typeid informally in chapter 2, and dynamic casts are covered later when we get into inheritance.

  • yash

    what is dynamic_cast and reinterpret_cast?

    • Alex

      dynamic_cast is used to convert pointers and references between base class and derived class objects. For example, if you have a base class A, and a derived class B, and a base class pointer A* that points to an object of type B, you'd use a dynamic_cast to convert the pointer from A* to B*. If this sounds like gibberish, it'll make more sense once you've learned about pointers and inheritance.

      reinterpret_cast is used when you want to change the type of an object but leave the underlying bits alone (static_cast will cause the underlying bits to be converted to the new type). There are very few situations in which this is necessary/desirable, and most of them are hacky.

      • AS

        Quoting "static_cast will cause the underlying bits to be converted to the new type".
        I understand that the under lying bits are re-interpreted and not converted totally.
        Or did I get this wrong?

  • Rajender

    If we assign a static type cast of different data type of a variable to itself, wouldn't it should give an error or not kindly look into this code

    • Alex

      No, there's no error here.

      Let's take this in two steps.

      First static_cast(k) happens, and k is explicitly converted into an int, with value 2.

      Second, k is assigned integer value 2. This results in an implicit conversion from int (2) to float (2.0), which is then assigned to float k.

      As a side note, the first line should be:

      Floating point literals default to type double without an f suffix.

      • Shiva

        A question on that side note:

        Floating point literals default to type double, but then, won't it be implicitly type converted into float so that the float variable 'k' can be initiated with it? Is it to avoid this conversion altogether that we add the 'f' suffix? Since 'k' is defined float, it won't be converted into double somehow. Or am I missing something?

        • Alex

          Yes, we add the f to avoid the conversion. If we tried to assign a double literal to a float variable, C++ would try to convert it, which could cause truncation or rounding errors to happen.

  • Gergő

    Hi Alex!

    "Because C-style casts are not checked by the compiler at compile type"

    Isn't "type" supposed to be "time" there?

    I'm working on a full Hungarian translation for the entire collection of chapters here and this gave me some minutes of head scratching.
    By the way, i'm just doing it to burn the info in deeper than by simply reading, but if you may be interested in turning this site to multilingual, you can send me a template showing exactly how you'd expect the translated material sent to you so you don't need to do any work with it other than opening up a folder to copy into. And when i'm done i'd send you the entire stuff in Hungarian. A couple thousand Hungarian clicks over time couldn't hurt you i guess...

    • Alex

      Thanks for catching that typo.

      The site currently doesn't have infrastructural support for multiple languages. I also actively update the articles for clarity and typo-fixing -- I'm not sure how I'd be able to keep translations up to date.

  • Rahul Agrawal

    this also are part of explicit type casting. Can you please add some information about this.Specially dynamic_cast. where to use static_cast and where to use dynamic_cast creates lots of confusion.

  • Shivam Tripathi it...thanku so much Alex...:)

  • Shivam Tripathi

    hii alex...once again need ur help..:)..consider this code snippet..

    [ int a=15;
      float c= static_cast <float> (a);
      std::cout<< a<<"t"<< &a <<std::endl;
      std::cout<< c <<"t"<< &c <<std::endl;
      return 0;
    o/p:- 15  0x23fe4c
          15  0x23fe48..

    my query is that suppose we need to use only float value further in our the memory being allocated to the 'int' one will be useless...can we free that??...why do such wastage of the memory...plzz help..

    • Alex

      Local variables exist until they go out of scope at the end of the block they are defined in. There's no way to manually deallocate them before that point.

      Honestly though, it doesn't matter. The memory use of an extra variable (or even tens of extra variables) is insignificant.

  • Todd


    "A cast represents a (an) explicit request"

    "making it less easy to make an inadvertent error" (I would say "making it harder...", but now I'm being picky)

  • Peter

    In the C-style casts example you have variable i1 but then you talk about nValue1

  • joel.giedt

    One common type casting that comes up all the time in codes I work with is switching between different types of pointers. The most unavoidable example is something like

    Float *ptr = (Float *)smalloc(num_bytes);

    Because smalloc() is like malloc in that it returns a void type. You might wonder why not use the new operator for dynamic allocation? The reason is that on the architecture we are using (e.g., BlueGene L/P/Q) we want to align the memory usage properly in order to avoid cache misses. So we write a function smalloc() that takes care of all that for us, which new would not do if we are using the GNU compiler (maybe IBM's compiler will do it automatically, I don't know). We can also write into it code to verify the allocation was successful and if not, report the class and function where the error occured,

    Float *ptr=(Float *)smalloc(num_bytes,cname,fname);

    Also Float is some typedef, probably float or double, depending on the precision we've decided to use.

    Another use, which looks dangerous, but we do it anyways because we care more about performance than C++ doctrine, is something like:

    int num_bytes = N*2*sizeof(Float);
    Complex *c=(Complex *c)smalloc(num_bytes);
    // next, code that fills in the array of complex numbers ...
    Float *temp=(Float *)c;
    // Now we want the norm of the complex vector, and we use an optimized function that say uses standard reduction algorithm to take advantage of multithreading on our 64-way processor, or maybe on a GPU accelerator:
    Float my_norm=norm(temp,N*2);

    By converting to Float array, the complex array looks just like an array of floats 2*N long and norm knows what to do with such an array. If norm is a library function that we a calling from some external package, it probably has no idea what to do with our abstract Complex type. So we trick it. Is it "dangerous"? Maybe, but so is driving a car.

    Another trick may be if we have to call MPI_Send() and MPI_Recv() to send the array of Complex numbers between compute nodes. Then Float* typically means something to these functions, but Complex* does not. It would be ridiculous to copy the array elements into a float array just to communicate them when a simple type casting does the job (provided we do not use the C++ standard complex class, but rather our own class with just two data elements --- note that they also cannot be private, again for performance reasons --- we'd be friending practically every function in our code, which is plain silly).

  • Chip Blach

    Casting is at the discression of the programmer. I have had cases where I have had to cast an integer
    as a array of 4 unsigned chars.
    If the program needs it, cast it, if it does not, dont do it.

    In c++ it is always better not to cast, but to stick with strict assignments which are provided.


  • spacedmonkey


    I just have a query about casting. When you cast a variable from one type to another in order to carry out some statement or other, is the variable permanently changed to this type or is it just temporarily changed at the point where the cast command is used?

    For instance:

    nValue1 is cast as a float in line 3 (and nValue2 is changed to a float as well I assume). Is nValue1 (and nValue2) a float from this point on in the program or does it retain its original type of int?

    • Anu

      Hi spacedmonkey,

      I tried to answer your running the following code:

      The output is 2.5, 10 and 4
      So, this means that the values of nValue1 and nValue2 are temporarily casted as floats, just for evaluating that expression.

    • They are temporarily cast. If you don't assign those temporary values to anything, they are lost. The original variable is not changed.

  • Alok

    Even after using static_cast, i am getting compiler warning "warning (etoa:1643): narrowing or signed-to-unsigned type conversion found: unsigned long to unsigned short".

    I am trying to assigned int variable to short int variable.

  • Abhishek

    This paragraph(and anything after it)went over my head::

    "The C style cast can be inherently misused, because it will let you do things that may not make sense, such as getting rid of a const or changing a data type without changing the underlying representation. C introduces a new casting operator called static_cast. A static cast works similarly to the C style cast, except it will only do standard type conversions, which reduces the potential for inadvertant misuse"
    I didn't get the difference b/w Cpp style cast,C style cast and static_cast............I think all of them do the same thing...only the syntax is different.????

    • The purpose of static_cast is to do normal conversion between types without runtime checks. C++ provides several other types of casts, including dynamic_cast, reinterpret_cast, and const_cast, all of which have different behavior.

      The problem with C-style casting is that it may use a static_cast, reinterpret_cast, or const_cast (or a combination thereof) depending on the situation, and we're not always sure which one(s) it's going to pick. That's why using static_cast is safer -- we're always sure what it's going to do, and if we try to do something it wasn't meant for, it will give us a warning.

      Here's an example of a C-style cast:

      Not only is this casting a char to an unsigned char, it's also tossing away the const. I think it's doing a reinterpret_cast and a const_cast combination. In any case, you can see that this is dangerous. Let's try using a C++ style static_cast instead:

      When we try to compile this, the compiler will complain:

      In other words, the C++ style casts give you more control over what type of casting you want to perform, and will warn you if you do something that violates the constraints on the cast. On the other hand, C-style casts will try to convert whatever you throw at it, regardless of whether it really makes sense to be doing so. This is dangerous and can lead to unexpected behavior.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]