4.3 — Object sizes and the sizeof operator

Object sizes

As you learned in the lesson 4.1 -- Introduction to fundamental data types, memory on modern machines is typically organized into byte-sized units, with each byte of memory having a unique address. Up to this point, it has been useful to think of memory as a bunch of cubbyholes or mailboxes where we can put and retrieve information, and variables as names for accessing those cubbyholes or mailboxes.

However, this analogy is not quite correct in one regard -- most objects actually take up more than 1 byte of memory. A single object may use 2, 4, 8, or even more consecutive memory addresses. The amount of memory that an object uses is based on its data type.

Because we typically access memory through variable names (and not directly via memory addresses), the compiler is able to hide the details of how many bytes a given object uses from us. When we access some variable x, the compiler knows how many bytes of data to retrieve (based on the type of variable x), and can handle that task for us.

Even so, there are several reasons it is useful to know how much memory an object uses.

First, the more memory an object uses, the more information it can hold.

A single bit can hold 2 possible values, a 0, or a 1:

bit 0

2 bits can hold 4 possible values:

bit 0 bit 1
0 0
0 1
1 0
1 1

3 bits can hold 8 possible values:

bit 0 bit 1 bit 2
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1

To generalize, an object with n bits (where n is an integer) can hold 2n (2 to the power of n, also commonly written 2^n) unique values. Therefore, with an 8-bit byte, a byte-sized object can hold 28 (256) different values. An object that uses 2 bytes can hold 2^16 (65536) different values!

Thus, the size of the object puts a limit on the amount of unique values it can store -- objects that utilize more bytes can store a larger number of unique values. We will explore this further when we talk more about integers.

Second, computers have a finite amount of free memory. Every time we define an object, a small portion of that free memory is used for as long as the object is in existence. Because modern computers have a lot of memory, this impact is usually negligible. However, for programs that need a large amount of objects or data (e.g. a game that is rendering millions of polygons), the difference between using 1 byte and 8 byte objects can be significant.

Key insight

New programmers often focus too much on optimizing their code to use as little memory as possible. In most cases, this makes a negligible difference. Focus on writing maintainable code, and optimize only when and where the benefit will be substantive.

Fundamental data type sizes

The obvious next question is “how much memory do variables of different data types take?”. You may be surprised to find that the size of a given data type is dependent on the compiler and/or the computer architecture!

C++ only guarantees that each fundamental data types will have a minimum size:

Category Type Minimum Size Note
boolean bool 1 byte
character char 1 byte Always exactly 1 byte
wchar_t 1 byte
char16_t 2 bytes C++11 type
char32_t 4 bytes C++11 type
integer short 2 bytes
int 2 bytes
long 4 bytes
long long 8 bytes C99/C++11 type
floating point float 4 bytes
double 8 bytes
long double 8 bytes

However, the actual size of the variables may be different on your machine (particularly int, which is more often 4 bytes).

Best practice

For maximum compatibility, you shouldn’t assume that variables are larger than the specified minimum size.

Objects of fundamental data types are generally extremely fast.

The sizeof operator

In order to determine the size of data types on a particular machine, C++ provides an operator named sizeof. The sizeof operator is a unary operator that takes either a type or a variable, and returns its size in bytes. You can compile and run the following program to find out how large some of your data types are:

Here is the output from the author’s x64 machine, using Visual Studio:

bool:           1 bytes
char:           1 bytes
wchar_t:        2 bytes
char16_t:       2 bytes
char32_t:       4 bytes
short:          2 bytes
int:            4 bytes
long:           4 bytes
long long:      8 bytes
float:          4 bytes
double:         8 bytes
long double:    8 bytes

Your results may vary if you are using a different type of machine, or a different compiler. Note that you can not use the sizeof operator on the void type, since it has no size (doing so will cause a compile error).

For advanced readers

If you’re wondering what ‘\t’ is in the above program, it’s a special symbol that inserts a tab (in the example, we’re using it to align the output columns). We will cover ‘\t’ and other special symbols in lesson 4.11 -- Chars.

You can also use the sizeof operator on a variable name:

x is 4 bytes

Fundamental data type performance

On modern machines, objects of the fundamental data types are fast, so performance while using these types should generally not be a concern.

As an aside...

You might assume that types that use less memory would be faster than types that use more memory. This is not always true. CPUs are often optimized to process data of a certain size (e.g. 32 bits), and types that match that size may be processed quicker. On such a machine, a 32-bit int could be faster than a 16-bit short or an 8-bit char.

4.4 -- Signed integers
4.2 -- Void

242 comments to 4.3 — Object sizes and the sizeof operator

  • Waldo Lemmer

    1.    Using a whole byte to store a Boolean value seems inefficient. Is this inefficiency addressed by the compiler or the CPU? If not, is it possible to create a type that addresses it (for example by storing multiple Booleans in a single byte)?

    2.    In the first code block on this page, wouldn’t it be better to align everything in neat columns? This could encourage the reader to also do so in other programs that he/she writes.

    This is how I wrote it:

    3. Visual Studio lets me choose between x86 and x64. The output for the above program looks exactly the same with both. How do I decide which one I should use?

    4. How do I change my profile picture for this website?

    Thank you for the great tutorial!

    • nascardriver

      1. You can store booleans in bits by using bitwise operators. Doing so is less efficient than using whatever your compiler gives you. Your compiler knows what you CPU is good at processing. In most cases that's a byte or even 4 bytes, even if it means wasting memory.

      2. Formatting is personal preference. As long as you're doing it consistently (eg. by using an auto-formatter), everything is ok.

      3. Use the 64 bit configuration, 32 bit is dead.

      4. Profile pictures are fetched from using your email address.

  • This code consumes me 10GB of ram lul

    #include <vector>

    // Max value
    unsigned int long a = 18446744073709551615;

    int main()
        std::vector<unsigned int long> vec(a);    

  • Sadra

    My system is 64-bit but why the code outputs the following:

    • Eru


      If you are using visual studio, the platform option might be set to x86 instead of x64.

      If thats the case, you can go to  " Build -> Configuration Manager " from the toolbar and change to x64.

      I don't have any other IDE installed but it's most likely that they too have a setting like that.

  • X

    why "sizeof" able to get the size?
    what's the technology behind this?

    • Josue

      My guess is that sizeof() belongs to the Standard Library. I could be wrong though.

    • James Clarks

      This is using Chinese technology to get the size of the corresponding data type. Why you have to ask a million questions now, There are 20+ chapters, you will get everything by the end.

  • a given data type is dependent on the compiler

    "You may be surprised to find that the size of a given data type is dependent on the compiler and/or the computer architecture!"

    I still don't know what the reason behind this? I Googled it and couldn't figure out the reason!

    • Eru


      "The idea behind int was that it was supposed to match the natural "word" size on the given platform: 16 bit on 16-bit platforms, 32 bit on 32-bit platforms, 64 bit on 64-bit platforms, you get the idea. However, for backward compatibility purposes some compilers prefer to stick to 32-bit int even on 64-bit platforms."

      This is what i could find as an answer from

      "The type int should be the integer type that the target processor is most efficiently working with. This allows great flexibility: for example, all types can be 64-bit. However, several different integer width schemes (data models) are popular. Because the data model defines how different programs communicate, a uniform data model is used within a given operating system application interface."

      And this is from the wiki page of C data types

  • Operator VS Function

    What is the difference between operator and a function? Both have follow the same pattern: parameters and return values and body! Why do they have different names?

    • Victor

      they are absolutely not the same thing.

      • Austin Snider

        They absolutely are the same thing.

        Under the hood C++ operators are implemented as functions. These operators can also be overloaded.


  • Callum

    Hello! First of all, I'm really enjoying these tutorials. Way better than YouTube! :)

    I have a question. Since Booleans only contain a single digit (0 or 1) why is the size of a Boolean 1 byte? It would make more sense if Booleans were 1 bit since the other 7 bits are not being used.

    Thanks again for these tutorials! :)

    • Hi! I'm not the author but hopefully I can help you too.

      Earlier you have read that computers have a limited number of memory addresses and a limited amount of memory.

      But that memory amount is so big that assigning a separate address to a single bit would mean that "available memory addresses" would run out before all bits get a separate address (8GB = 64 billion bits which is a lot). Instead each byte gets their separate address (8 billion is still many but not THAT many).

      And because only each bytes get a separate memory address, the smallest amount of data we can use to save a variable is 1 byte. Which means that even if you save a variable that can be represented by a single bit, it will still occupy 8 bits or 1 byte.

      Now, why can't we leave those 7 bits unused? Because why would we? Why is it better to take up 8 bits but only use 1 than take up 8 bits and use all even if you really only need 1?

      Another reason can also be that computers are optimized for certain data sizes. If a computer is optimized for 8, 32 and 64 bit data types than using 8 bits is faster than using only 1.

      PS: I'm not a professional nor a teacher so take what I say with a grain of salt but as far as I know this is the correct answer.

  • Edgar

    If i wanted to use a "data type" as an argument, what would you use? For example this code used to go from bytes to bits:

    #include <iostream>
    #include "sizeof.h"

    int main()
        std::cout<<"What type size you want: \n"; // asks user input
        char x{}; // THIS IS WHAT I DON't UNDERSTAND
        std::cin >> x;
        bitSize(sizeof(x)); //Converts the size of bytes into bits.

        return 0;

    Thanks in advance. I've learned CPP from using your tutorials. It's not often that you can find text based stuff that's 1000x better than YouTube

    • nascardriver

      That's not possible. Types are a compile-time concept, they don't exist at run-time (For the most part).
      The only thing you can do is to read a string from the user, then use that string to call `sizeof` with the correct type. For example

  • Omran

    please i'm confused i saw many videos on YouTube , isn't 2 digits (like 0 or 1 )
    counts as a bit ? , for instance we have 01 = 1bit or 10 = 1bit , is that right ? .
    please someone explain ! , one more question , 3 bits can hold integers values between "0 <=
    integers values < 8 " right ?

  • mars

    Great tutorials.
    I wanted to ask if sizeof() is an operator or a function. It looks like a function to me because of (parenthesis) and takes parameters and return a value.

  • Justin

    QUESTION: The sizeof function returns an unsigned int. Assuming that that uses 4 bytes, the maximum number that it can store is 4294967295. What if I had an array that was bigger than 4294967295 in size, for example, an array of 1000000000 long-type numbers? If I took the sizeof that array, what would it return?

  • Raffaello

    can I still follow this tutorial to its end and study C++ further even if I'm *really* bad at math? :)

  • Taras

    Thanks for lesson! Everything is very clear. One question to you. As it seen above the actual sizes of int and long are the same 4 bytes, is it correct to state that they are equal on the prescribed machine, and the highest value is 2^32 ? So what is the point in using long?

    • nascardriver

      On this exact machine, they are the same, but they are not the same on every machine.
      A 32 bit integer can store 2^32 values, but keep in mind that it can store non-positive values. The highest value of an `unsigned` 32 bit int is (2^32 - 1). -1 because it has to hold 0. For a signed int, the highest value is (2^31 - 1), because we have to use 1 bit to indicate the sign.

  • Jha

    Please fix the wchar_t size in "Fundamental data type sizes".
    In the table we have now 1, instead of 2 (or even more on some systems).
    A few lines below the sizeof operator example output displays 2.


  • Apaulture

    How can a float type hold more values than an int type although their sizes are the same? Is it because the computer allocates more memory for a float as the value it holds is increased?

    • Alex

      Floating point numbers don't "hold more values" -- they do have a larger range, which they gain by losing precision (they can't precisely represent every number in the range).

  • Dileep

    if 'double' and 'long double' both have same size whats the advantage of using 'long double'?

  • Air Paul

    CPUs are often optimized to process data of a certain size. Any reasons???

  • Air Paul

    It is given in this section that "C++ only guarantees that each fundamental data types will have a minimum size", does C++ guarantees about the range of values a particular data type holds.

  • Chayim

    "To generalize, an object with n bits can hold 2n (2 to the power of n"
    What is a -n bit-? It was never explained in the lesson

  • Mike

    Please tell me there is an easier way to rename a .cpp file you're working in. Many times while testing, I end up with code that I would like to keep for reference, but for the life of me I can't seem to find an option in Visual Studio that allows you to do this. And the last time I renamed one from the Solution Explorer, I could never get it to reopen. It kept saying it was missing a number of things. So I've just been copying and pasting the code in a new solution each time, which just seems silly.

  • Ganesh Koli

    Hello Alex,
    Thank you for the great tutorial.
    I have question related to sizeof() operator,  new & delete.

    Q1. How to use sizeof() operator to calculate the correct size of array using pointer?

    In above code i have a pointer of 'Student' type which is pointing to the array of Student type.
    Suppose in method i received the pointer. How i get to know if this pointer is pointing to the one object or array of object ? and if it is pointing to array then how to calculate the size of array.

    To delete the one object we simply use 'delete'.
    To delete array of objects we use delete[], but we are not passing the size of array.
    Q2. so how can 'delete' calculate the size of array using pointer only ? and how could use the similar technique in first question?

    Thanks alot.

    • You can't obtain the array size from a pointer. `delete[]` uses some internal magic, inaccessible to you. If you need to know the size after the array decayed to a pointer, pass the array's size as an extra argument or use a standard container (covered later).

      • Ganesh Koli

        Thank you nascardriver,
        As you mentioned the magic 'delete' has to find out the size of array. Does it implementation dependent ? or C++ standard provide the specification of delete to get the size of array ?

        My thoughts about why it works for delete. Thanks to correct me.
        - Pointer can point to any memory location which can be on heap or stack or data segment(i mean global variable). Pointer treats them same as a memory location.

        - 'new' allocates memory in heap. 'delete' release it.
        - When we allocate array in heap then its allocate extra byte/bytes to keep the size and other information. Such extra byte is not allocated in stack array.
        In delete syntax pointer should be only pointing to the memory allocated in heap. we just need to tell delete() whether we want to delete one object or array. if it is array then delete use the extra byte the get the size information.

        I think 'delete' can use this technique because it is sure that the memory allocated in heap; however in normal pointer we can never be sure, if pointer is pointing to the local array or array in heap. So pointer can not calculate the size.

        I am confused. Its just my thoughts. Please correct my understanding.

        • Most of the underlying memory model is unspecified in C++. Compiler developers can keep track of the size however they want. A common implementation is to allocate some extra memory when `new[]` is called and store the array's size there.

  • Ashwathy Anil Alappatt

    Hi , one query , why is int shown as 2 bytes , when it should be 4 bytes , according to this

    4 bytes
    For example, in 16-bit machines, sizeof (int) was 2 bytes. 32-bit machines have 4 bytes for int . It has been considered int was the native size of a processor, i.e., the size of register. However, 32-bit computers were so popular, and huge number of software has been written for 32-bit programming model.

  • (name redacted)

    Why does bool data type have to take 1 byte?
    It can use a bit for true and false

    • Your CPU is good at working with types whose size is a power of 2 (1, 2, 4, 8), not so much with individual bits. Some implementations might even use 4 byte sized `bool`s.

    • Alex

      Modern machines typically have memory that is byte addressable, meaning they can only read/write a minimum of 1 byte. So even though a bool only technically requires 1 bit, we have to read/write 7 other bits of wasted space to access that 1 bit.

  • alfonso

    Well, long double is 16 bytes on my system. :)

    Code::Blocks and Arch Linux 64 bit.

  • Vincent C


    I have questions on the maximum value of int type in C++. You mentioned that the minimum byte size of int is 2.

    However, the documentation in Microsoft:

    stated the INT_MAX constant refers to 2147483647, which means the integer is 4 bytes.

    If the minimum byte size of integer is 2, why would the constant be defined as a 4-byte value? Does it mean that the program using that constant in some computers will crash if the int type in the computer architecture is only 2 bytes?

    • INT_MAX is a define of msvc++, it's not standard, don't use it. As long as that compiler uses 4 bytes for ints, there is no problem. If microsoft decides to use a different sized integer, they need to update the define too.

  • Louis Cloete

    @Alex, in your "Key insight" block, you explain why it isn't necessary on a modern machine to try to use the smallest variable possible. It is, as I understand, not only not necessary, but also less performant in some cases. As far as I know, 4-byte integers are the fastest on modern 32-bit and 64-bit platforms. I was also told not to worry about sizes and just use Integer when I learnt Pascal, but the penny dropped only when I read that it is slower to use other types (and my teacher programmed in C in the '70s, so he would know what he is talking about when he says you can use four-byte integers safely today ;-)).

    This long-winded thing is to suggest you drop a mention about the speed benefit of int over short and char into the block.

    • Alex

      While you're not wrong, any optimizations that have a negligible impact on memory usage also likely have a negligible impact on performance.

      I added a point about performance to a new section at the end of the lesson.

  • Em


    You wrote that:
    An object that uses 2 bytes can hold 2^16 (65536) different values!

    I believe that this was a typo, and you meant to say 16 bytes, not 2 bytes.

  • Jules

    I hope someone like nascardriver or Alex sees this,
    so I quite don't understand the relationship between number of bytes that a datatype has v/s actual values it can hold.
    for eg:
    An standard int is of 4 bytes, so the number of values it can hold are 2^4 = 16.
    but the value range an integer is -
    -32,768 to 32,767 or -2,147,483,648 to 2,147,483,647

    Also what is up with there being different datatypes of char?,if a char holds only one character why are there different types of chars like - char,wchar_t,char16_t and char32_t, If i wanted to store a string wont i just declare an array?

    i'm kinda lost here.

    • Hi Jules!

      > An standard int is of 4 bytes, so the number of values it can hold are 2^4 = 16.
      Both nope. An int doesn't have to be 4 bytes and your calculation is off.
      Assuming a 4 byte int:
      4 bytes are 32 bits. That makes 2^32 possible values. The range is -(2^31) to (2^31)-1

      > char
      1 byte

      > wchar_t
      2 bytes (No guarantees, I'm doing this from memory)

      > char16_t
      2 bytes

      > char32_t
      4 bytes

      The larger char types are required to store non-ascii characters, because those can take up more than 1 byte.
      You can store unicode strings in char arrays, but the individual characters will be split into multiple chars.

      • Jules

        Hi nascar!

        thanks for replying on such a short notice, it seems i mistook bits for bytes here.
        as you said assuming that an integer has 4 bytes, the possible values would be 2^32 = 4294967296
        now wont the range be: -2147483648 to +2147483647, your definition would have the range as -4294967296 to +4294967296, wont it?

        also what do you mean by -
        >but the individual characters will be split into multiple chars.
        thanks for your time.


        • > your definition would have the range as -4294967296 to +4294967296, wont it?
          It won't. I used 2^31 in my range, not 2^32

          > also what do you mean by

          The lightning symbol has a value of 0x21AF ( ). Too much for a single char.

          Running the code and giving a lightning as input results in

          input: ↯
          length: 3
          0: � (-30)
          1: � (-122)
          2: � (-81)

          We input a single character, but we need 3 chars to store it. Each char on it's own doesn't make a whole lot of sense. But my terminal (and presumably yours too) knows how to print the 3 successive chars as a single character.

  • Quyết

    Hi, i have a question...
    look gt1 function and gt2 function...

    which good ???

    • The first solution is better. Avoid recursion (A function calling itself).

  • Hi Alex!

    I have doubts about your "C++ guarantees that the basic data types will have a minimum size" table.
    The standard only states
    "There are five standard signed integer types : “signed char”, “short int”, “int”, “long int”, and “long long int”. In this list, each type provides at least as much storage as those preceding it in the list."
    N4762 § 6.7.1 (2)

    To me this sounds like a long long int could be a 1 byte sized type.

    • Alex

      The C++ standard does only explicitly state as you say. However, the C++ standard apparently references the C standard in this regard, and the C standard implies a minimum range of numbers that each type must be able to hold. Implicitly, that implies a minimum size.

      Here's the minimum sizes from the C standard: (see page 22)

      Also see for some discussion about this.

      Finally, note that corroborates this understanding.

Leave a Comment

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