>
>
>
V1055. The 'sizeof' expression returns …


V1055. The 'sizeof' expression returns the size of the container type, not the number of elements. Consider using the 'size()' function.

The analyzer has detected a variable of type "STL-like container" passed as an argument to the 'sizeof' operator.

Consider the following example:

#include <string>

void foo(const std::string &name)
{
  auto len = sizeof(name) / sizeof(name[0]);
  ....
}

The 'sizeof(name)' expression yields the size of the container type used for implementation rather than the total size of elements in bytes in that container (or simply the number of elements). For example, the typical 'std::string' implementation can contain 3 pointers (libc++ standard library, 64-bit system), i.e. 'sizeof(name) == 24'. However, the size of the real string stored in it is usually different.

Errors of this type can be caused by refactoring old code:

#define MAX_LEN(str) ( sizeof((str)) / sizeof((str)[0]) - 1 )
typedef char MyString[256];

void foo()
{
  MyString str { .... };
  ....
  size_t max_len = MAX_LEN(str);
}

Changing the type of the 'MyString' alias from 'char[256]' to 'std::string' will cause the expression evaluating the maximum string length to return an incorrect result.

To get the real size of STL-like containers, use the public member function '.size()':

#include <string>
void foo(const std::string &name)
{
  auto len = name.size(); 
}

If it is indeed the size of the container implementation itself that you want to evaluate, a better decision would be to pass the type of the container as the operand of 'sizeof' – either directly or using the 'decltype' (C++11) operator for variables. This way, your intention will be clear to others. For example:

#include <string>

void foo(const std::string &str)
{
  auto string_size_impl1 = sizeof(std::string);
  auto string_size_impl2 = sizeof(decltype(str));
}

The diagnostic also knows of the 'std::array' container and does not issue the warning on it when that container is used as the operand of 'sizeof':

template <typename T, size_t N>
void foo(const std::array<T, N> &arr)
{
  auto size = sizeof(arr) / sizeof(arr[0]); // ok
}

Starting with the C++17 standard, it is recommended that you use the free 'std::size()' function, which can handle both the built-in arrays and all types of containers that have the public member function '.size()':

#include <vector>
#include <string>
#include <set>
#include <list>

void foo()
{
  int arr[256] { .... };

  std::vector vec { .... };
  std::string str { .... };
  std::set    set { .... };
  std::list  list { .... };

  auto len1 = std::size(arr);
  auto len2 = std::size(vec);
  auto len3 = std::size(str);
  auto len4 = std::size(set);
  auto len5 = std::size(list);
}

This diagnostic is classified as: