Initializing an Array using Size of Operator? - c++

I have an array that I would like to initialize
char arr[sizeof(int)];
Would this expression evaluate to a compile time constant or result in a function call?

char arr[sizeof(int)];
As far as the language is concerned, it is fine, though the array is only declared (and defined), it is NOT initialized if it is a local variable. If it is declared at namespace level, then it is statically zero-initialized.
Note that sizeof(int) is a constant expression of size_t type; its value is known at the compile time.

This is an initialization:
char arr[sizeof(int)] = { 'A', 'B', '0', 'F' };
This of course assumes that sizeof(int) is (at least) 4, or it will fail to compile.
And to answer the actual (new) question:
sizeof() is a compile time operator. In C++ [according to the standard, some compilers do allow C style variable length arrays], it will not result in anything other than a compile time constant. In C, with variable length arrays, it can become a simple calculation (number of elements * size of each element - where number of elements is the variable part).

There is no initialization here. There's nothing wrong with declaring or defining an array with sizeof(int) elements, except that it might look a little odd to readers of the code. But if that's what you need, that's what you should write.

It really depends on how you intend to use the array.
sizeof(int) may vary with different implementations so you just need to be careful how you access the elements in the array. Don't go assuming that an element that is accessible on your machine is accessible on another, unless it's within the minimum sizes specified in the C++ standard.

sizeof is evaluated at compile time, the only time sizeof would would be run time evaluated would be in the case of variable length arrays in C99 code or in gcc or other c++ compilers that support VLA as an extension. So this code is valid:
char arr[sizeof(int)];
Although if it is local variable it won't be initialized.

Related

Why sizeof() of a string variable always return the same number even when content changes?

This is a rather simple problem but is pretty confusing.
string R = "hhhh" ;
cout<< sizeof( R )<<endl;
OUTPUT:
4
Variation:
string R = "hhuuuuuuhh" ;
cout<< sizeof( R )<
OUTPUT2:
4
What is going wrong ? Should I use char array instead ?
Think of sizeof being compile-time evaluable. It evaluates to the size of the type, not the size of the contents. You can even write sizeof(std::string) which will be exactly the same as sizeof(foo) for any std::string instance foo.
To compute the number of characters in a std::string, use size().
If you have a character array, say char c[6] then the type of c is an array of 6 chars. So sizeof(c) (known at compile-time) will be 6 as the C++ standard defines the size of a single char to be 1.
sizeof expression returns the size required for storage of the type expression evaluates to (see http://en.cppreference.com/w/cpp/language/sizeof). In case of std::string, this contains a pointer to the data (and possibly a buffer for small strings), but not the data itself, so it doesn't (and can't) depend on string length.
Your string variable will consist of a part most often stored on the stack, which has fixed dimensions. The size of this part is what's returned by sizeof (). Inside this fixed part is a pointer (or reference) to a part stored on the heap, which actually contain your characters and has a varying size. However the size of this part is only known at runtime, while sizeof () is computed at compile time.
You may wonder why. Things like this are both the strength and the weakness of C++. C++ is a totally different beast from e.g. languages like Python and C#. While the latter languages can produce all kinds of dynamically changing meta-data (like the size or type of a variable), the price that is paid is that they're all slow. C++, while being a bit 'spartan', can run rings around such languages. In fact most 'dynamic' languages are in fact implemented (programmed) in C/C++.

Does sizeof(int) (or any sizeof any simple data type) cost anything at runtime?

I would have thought that all the necessary info would be known at compile time and the compiler could insert a constant value.
Does this indeed happen?
No. sizeof(int) results in a constant expression of size_t type, which means its value known at compile time. NO RUNTIME OVERHEAD!
No. It is a compile time thing.
No, in C++, sizeof is always evaluated in compile time.
Note that it's not true in C, the exception is variable length arrays.

about power of sizeof operator in C++

I am reading Modern C++ design. It was mentioned about sizeof opeator as following description. Following paragraph is explained from generic programming point of view.
There is a surprising amount of power in sizeof: You can apply sizeof to any expression, no matter how complex, and sizeof returns its size without actually evaluating that expression at runtime. This means that sizeof is aware of overloading, template instantiation, conversion rules—everything that can take part in a C++ expression. In fact, sizeof conceals a complete facility for deducing the type of an expression; eventually, sizeof throws away the expression and returns only the size of its result.
My question is what does author mean sizeof returns its size with out actually evalutating the exression at runtime. And also in last line it was mentioned that sizeof throws away the expression. Request help in understanding these statements, it would be good if it is done with example.
Thanks
what does author mean sizeof returns its size with out actually evalutating the exression at runtime.
It means that sizeof(1/0) will yield sizeof(int), even though 1/0 would normally abort the program, because division by zero is a runtime error. Also, for any p declared as T* p, sizeof(*p) will yield sizeof(T) no matter what value is stored in p, even if p is dangling or not initialized at all.
sizeof is evaluated at compile time: the compiler computes the type of the expression that follows the sizeof operator. This is done once and for all by the compiler, hence the sentence “without actually evaluating that expression at runtime”.
The compiler computes the type, then it is able to deduce the size of the expression from the type, and then, still at compile time, the whole sizeof expression is replaced by the calculated size. So the expression itself does not make it into the executable code. That's what the sentence “sizeof throws away the expression and returns only the size of its result” means.
The following gives you the sizeof of the type that i++ has, which is int (usually an int has 4 or 8 bytes, so it will likely give you value 4 or 8). However, since the expression is not evaluated, no runtime action is done for the expression.
int i = 0;
sizeof(i++);
Evaluating an expression basically means to execute its side effects (e.g incrementing a variable) or reading values from memory or registers at runtime. So in some sense sizeof "throws away" its operand, since it does not really perform the runtime operation it specifies (the value of i will still be zero).
The compiler needs to calculate the sizes of types/structs/classes for various operations. The sizeof operator makes these sizes available to your program as a constant. So for example, if you do sizeof(int) the compiler knows how big an int is (in bytes) and will insert that value instead. The same applies for more complex things like sizeof(myVariable) with myVariable being of type MyClass: the compiler does know how much space MyClass takes up and thus can insert that value.
The point is that this evaluation takes places at compile-time: the result is a number. During runtime, the evaluation does not need to be done again.
It means int j=sizeof(int); would be compiled to int j=4;
I have read the compiled assembly, there is no actually calc during execution!

Difference between Array initializations

Please see the following statements:
char a[5]="jgkl"; // let's call this Statement A
char *b="jhdfjnfnsfnnkjdf"; // let's call this Statement B , and yes i know this is not an Array
char c[5]={'j','g','k','l','\0'}; // let's call this Statement C
Now, is there any difference between Statements A and C?
I mean both should be on Stack dont they? Only b will be at Static location.
So wouldn't that make "jgkl" exist at the static location for the entire life of the program? Since it is supposed to be read-only/constant?
Please clarify.
No, because the characters "jgkl" from Statement A are used to initialize a, it does not create storage in the executable for a character string (other than the storage you created by declaring a). This declaration creates an array of characters in read-write memory which contain the bytes {'j','g','k','l','\0'}, but the string which was used to initialize it is otherwise not present in the executable result.
In Statement B, the string literal's address is used as an initializer. The variable char *b is a pointer stored in read-write memory. It points to the character string "jhdfjnfnsfnnkjdf". This string is present in your executable image in a segment often called ".sdata", meaning "static data." The string is usually stored in read-only memory, as allowed by the C standard.
That is one key difference between declaring an array of characters and a string constant: Even if you have a pointer to the string constant, you should not modify the contents.
Attempting to modify the string constant is "undefined behavior" according to ANSI C standard section 6.5.7 on initialization.
If a[] is static then so is c[] - the two are equivalent, and neither is a string literal. The two could equally well be declared so that they were on the stack - it depends where and how they are declared, not the syntax used to specify their contents.
the value "jgkl" may never be loaded into working memory. Before main is ever called, a function (often called cinit) is run. One of the things this function does is initialize static and file-scope variables. On the DSP compiler I use, the initial values are stored in a table which is part of the program image. The table's format is unrelated to the format of the variables that are being initialized. The initializer table remains part of the program image and is never copied to RAM. Simply put, there is nowhere in memory that I can reliably access "jgkl".
Small strings like a might not even be stored in that table at all. The optimizer may reduce that to the equivalent (pseudoinstruction) store reg const(152<<24|167<<16|153<<8|154)
I suspect most compilers are similar.
A and C are exactly equivalent. The syntax used in A is an abbreviation for the syntax in C.
Each of the objects named a and c is an array of bytes of length 5, stored at a certain location in memory which is fixed during execution. The program can change the element bytes at any time. It is the compiler's responsibility to decide how to initialize the objects. The compiler might generate something similar to a[0] = 'j'; a[1] = 'g'; ..., or something similar to memcpy(a, static_read_only_initialization_data[1729], 5), or whatever it chooses. The array is on the (conceptual) stack if the declaration occurs in a function, or in global writable memory if the declaration occurs at file scope.
The object named b is a pointer to a byte. Its initial value is a pointer to string literal memory, which is read-only on many implementations that have read-only memory, but not all. The value of b could change (for example to point to a different string, or to NULL). The program is not allowed to change the contents of jhdfjnfnsfnnkjdf", though as usual in C the implementation may not enforce this.
C-Literals always are read-only.
a) allocates 5 bytes memory and store the
CONTENT from literal incl. '\0' in it
b) allocates sizeof(size_t) bytes
memory and store the literal-address in it
c) allocates 5 bytes memory and
store the 5 character-values in it

Is sizeof in C++ evaluated at compilation time or run time?

For example result of this code snippet depends on which machine: the compiler machine or the machine executable file works?
sizeof(short int)
sizeof is a compile time operator.
It depends on the machine executing your program. But the value evaluates at compile time. Thus the compiler (of course) has to know for which machine it's compiling.
As of C99, sizeof is evaluated at runtime if and only if the operand is a variable-length array, e.g. int a[b], where b is not known at compile time. In this case, sizeof(a) is evaluated at runtime and its result is the size (in bytes) of the entire array, i.e. the size of all elements in the array, combined. To get the number of elements in the array, use sizeof(a) / sizeof(b). From the C99 standard:
The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an
integer constant.
Note that all of this is different from what you'd get if you allocated an array on the heap, e.g. int* a = new int[b]. In that case, sizeof(a) would just give you the size of a pointer to int, i.e. 4 or 8 bytes, regardless of how many elements are in the array.
sizeof is evaluated at compile time, but if the executable is moved to a machine where the compile time and runtime values would be different, the executable will not be valid.
Anon tried to explain this, but still he nor no one else has stated that your compiler has flags to indicate what processor you are compiling for. This is how sizeof short is known at compile time.
I however feel that any desktop compiler should push out code compatible with desktops. I think the OS provides certain abstractions around this. Even though I hear that windows machines have different architecture from Macintosh machines.