Byte alignment, sizeof, strlen, _countof, offsetof, _msize

一、sizeof

The return value of sizeof() is best saved with size_t. Under x86 and x64, this type has different representations, unsigned int (32 bits), unsigned __int64 (64-bit)

#include <iostream>
#include <string>
#include <vector>

int main()
{
    int arrx[20];
    auto n = _countof(arrx); //n = 20, the return value type is unsigned int. The macro _countf is defined in stdlib.h, c++ can also be used if the vector header file is included.
    
    //The type of sizeof return value is size_t, unsigned int (32 bits), unsigned __int64 (64 bits)
    char ch1[] = "HelloWorld";
    char* ch2 = ch1; //sizeof(ch2)
    int arr1[] = { 1,2,3,4,5,6,7 };
    int* arr2 = arr1;
    std::string str1 = "HelloC + + ";
    std::string str2;

    size_t s1 = sizeof(ch1); //11, "HelloWorld\0" is the space occupied by the memory, so it contains the last string end symbol \0, so it is 10 + 1=11
    size_t s2 = sizeof(ch2); //Depends on the compiler platform, sizeof(ch2) gets the size of the pointer, x64 is 8, x86 is 4
    size_t s3 = sizeof(str1); //sizeof(str) gets the size of the string object, which is a fixed value and has nothing to do with the specific content of str.
    size_t s4 = sizeof(str2); //64-bit: 40, 32-bit: 28
    size_t s5 = sizeof(arr1); //28 An int occupies 4 bytes, 7*4=28
    size_t s6 = sizeof(arr2); //The size of the pointer depends on the compiler platform, 32-bit: 4, 64-bit: 8

    size_t s01 = sizeof((*ch1)); //1
    size_t s02 = sizeof((*ch2)); //1
    size_t s03 = sizeof((*arr1)); //4
    size_t s04 = sizeof((*arr2)); //4 The size obtained by dereferencing is the size of the first element type char:1,int:4

    size_t s7 = str1.length();//8, the length of the string, as many characters as there are, excluding the string terminator \0
    size_t s8 = strlen(ch1); //10, strlen(str1) error, the parameter of strlen is const char*, the length of the string is as many characters as there are
    size_t s9 = str1.size(); //8, same as str.length(), size can also be used to obtain the size of the container

    std::vector<std::string> vec;
    vec.emplace_back("abcdef");
    vec.emplace_back("123");
    vec.emplace_back("qwert");
    size_t s10 = vec.size(); //3
    size_t s11 = sizeof(vec); //It has nothing to do with the number of elements, 64-bit: 32, 32-bit: 16, it should store four pointers (not sure)
    size_t s12 = sizeof(std::vector<bool>); //bool is 1/2 larger than other types, that is, 64:48, 32:24,
    size_t s13 = sizeof(std::vector<int>); //16,32
    size_t s14 = sizeof(std::vector<std::string>); //16,32
    size_t s15 = sizeof(std::vector<char>); //16,32

    return 0;
}

2. Byte alignment

#include <iostream>

int main()
{
    struct s1 //16
    {
        int i;
        char c;
        double d;
    };
    struct s2 //16
    {
        double d;
        char c;
        int i;
    };
    struct s3 //16
    {
        char c;
        int i;
        double d;
    };
    struct s4 //24
    {//The type that takes up the largest space in the structure is 8(double), 1 + 7 + 8 + 4 = 20 is not a multiple of 8, so 4 bytes need to be filled to satisfy sizeof(double)=a multiple of 8
        char c;
        double d;
        int i;
    };
    std::cout << sizeof(s1) << sizeof(s2) << sizeof(s3) << sizeof(s4) << std::endl;
#pragma pack(push) //Save the alignment status push and pop are a pair, there is no need to wrap them with push and pop, pack(n) will take effect on all subsequent sizeof
#pragma pack(4) //Set to 4-byte alignment
    struct t1
    {
        char m1;
        double m4;
        int m3;
    };
    std::cout << sizeof(t1) << std::endl; //16
#pragma pack(pop)//Restore alignment state
    struct t2
    {
        char m1;
        double m4;
        int m3;
    };
    std::cout << sizeof(t2) << std::endl; //24

    return 0;
}

Three, string length

cstring header file (C-style string)

strlen(str) calculates the length of the string (returns the number of characters, excluding the ‘\0’ at the end)

string header file (std::string)

str.size() returns the length of the string (including the trailing null character, that is, spaces are also counted, there is no ‘\0’ at the end of the string type string)

CString header file (MFC)

str.GetLength() returns the number of characters (excluding the trailing null character)

Four. sizeof (common types)

1.sizeof(std::string)

Reprint: The layout of string in memory

Name X86 (number of bytes) X64 (number of bytes)
Allocator 4 8
Original string Data position 15 + 1, contains up to 15 characters plus a terminator ‘\0’ 15 + 1, contains up to 15 characters plus a terminator ‘\0’
Character length Size 4 8
Current capacity Capacity 4 8
Total 28 40

We will only discuss 32-bit programs below

  • For strings 15 characters or less in length:

The data will be saved to a total of 16 bytes of Data. If string is a temporary variable, the entire string data is located on the stack.

  • For strings with data larger than 15 characters:

An additional data area will be allocated on the heap, all data will be filled into the heap, and then the heap pointer will be assigned to the first pointer position of Data (the first 4 bytes of Data)

2.sizeof(container)

Container x64 x86
deque 40 20
vector 32 16

3.sizeof(class)

class X{};
class Y : public virtual X {};
class Z : public virtual X {};
class A : public Y,public Z {};

sizeof(X) //1
sizeof(Y) //4
sizeof(Z) //4
sizeof(A) //8

X is 1 because the compiler has inserted 1 char into it, so that its object can have its own independent address Y in the memory. Z is because the pointer A of the virtual base class table contains Y and Z. 8

5. Some methods for getting the number of bytes or elements

_countof

windows macro, used to calculate the number of elements in a statically allocated array. The return value type is unsigned int, which must be statically allocated array, cannot be a pointer

char s1[] = "12345";
int s2[] = { 1,2,3,4,5 };
int* s3 = new int[10]();

auto ret1 = _countof(s1); //6, including '\0'
auto ret2 = _countof(s2); //5
//auto ret3 = _countof(s3); //error

offsetof

offsetof will generate an integer constant of type size_t, which is the byte offset of a structure member relative to the beginning of the structure. The members are given in member-designator and the name of the structure is given in type.

_msize

To obtain the actual size of the content pointed to by the pointer (not the size of the pointer), you can only obtain the size of the content pointed to by the pointer from new or malloc.

#include <iostream>

void fun(int* p)
{
std::cout << sizeof(p) << '\
'; //8 (x64)
std::cout << _msize(p) << '\
'; //40 = 4*10
}

int main()
{
int* p = new int[10]();
int p1[] = { 1,2,3 };

fun(p);
//fun(p1); //It is not a pointer from new or malloc, the program will crash

return 0;
}