60

The following code

#include <iostream>    
using namespace std;

int main()
{
    const char* const foo = "f";
    const char bar[] = "b";
    cout << "sizeof(string literal) = " << sizeof( "f" ) << endl;
    cout << "sizeof(const char* const) = " << sizeof( foo ) << endl;
    cout << "sizeof(const char[]) = " << sizeof( bar ) << endl;
}

outputs

sizeof(string literal) = 2
sizeof(const char* const) = 4
sizeof(const char[]) = 2

on a 32bit OS, compiled with GCC.

  1. Why does sizeof calculate the length of (the space needed for) the string literal ?
  2. Does the string literal have a different type (from char* or char[]) when given to sizeof ?
CsTamas
  • 4,103
  • 5
  • 31
  • 34

2 Answers2

136
  1. sizeof("f") must return 2, one for the 'f' and one for the terminating '\0'.
  2. sizeof(foo) returns 4 on a 32-bit machine and 8 on a 64-bit machine because foo is a pointer.
  3. sizeof(bar) returns 2 because bar is an array of two characters, the 'b' and the terminating '\0'.

The string literal has the type 'array of size N of const char' where N includes the terminal null.

Remember, arrays do not decay to pointers when passed to sizeof.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 12
    +1, but the type is actually 'array of N const characters' (const is not optional) – David Rodríguez - dribeas Sep 08 '09 at 06:02
  • 6
    @dribeas: yes; I was ignoring the qualifiers, but you are pedantically correct. – Jonathan Leffler Sep 08 '09 at 06:13
  • 14
    @JonathanLeffler ... the best kind of correct, especially when it comes to programming – Alex Marshall May 01 '14 at 22:12
  • the fact that the comment about `const` appeared minutes after the answer puts a smile on my face. – CplusPuzzle Jul 17 '18 at 08:04
  • For 2., if memory serves, it's **NOT** guaranteed to be 4 or 8, according to the C standard. However the _spirit_ is correct - it will be the `sizeof(const char *)`, whatever that **pointer size** may be, and of course has no bearing on the actual length of the string. On some platforms/architectures/in some compilers (historically), pointer sizes and layouts changed depending on the type. This is why, for example, you must _explicitly_ cast pointers to their expected types (if they differed) in variadic function calls since the cast could change the pointer value entirely. – Qix - MONICA WAS MISTREATED Nov 19 '20 at 03:07
  • @AlexMarshall, I heard technically correct was the best kind of correct. But I think you're technically correct in this case. I'll update my _a posterioris._ – SO_fix_the_vote_sorting_bug Dec 29 '22 at 23:13
14

sizeof returns the size in bytes of its operand. That should answer question number 1. ;) Also, a string literal is of type "array to n const char" when passed to sizeof.

Your test cases, one by one:

  • "f" is a string literal consisting of two characters, the character f and the terminating NUL.
  • foo is a pointer (edit: regardless of qualifiers), and pointers seem to be 4 bytes long on your system..
  • For bar the case is the same as "f".

Hope that helps.

Michael Foukarakis
  • 39,737
  • 6
  • 87
  • 123
  • Why is a `char[]` the same as a striong literal though? I'm not a C/C++ expert, but I thought that `char[]` and `char*` were interchangable? – Matthew Scharley Sep 08 '09 at 05:58
  • +1 on the general answer (and for speed :) A couple of precisions: foo IS a pointer (essentially qualifier does not apply) and in C++ the type is always "array of n const char" (constant-ness is not optional) – David Rodríguez - dribeas Sep 08 '09 at 06:01
  • @dribeas: right you are, const always applies. @Matthew: char* and char[] are only the same under certain circumstances, the sizeof operator is not one of them. – Michael Foukarakis Sep 08 '09 at 06:09
  • 2
    @Matthew: Nope, arrays and pointers are *not* interchangeable. An array can be passed whenever a pointer is expected, as it *decays* to a pointer. But as long as the type is an array, it is *not* the same as a pointer. – jalf Sep 08 '09 at 10:35