Pretty simple program, I'm just testing the sizeof() function and trying to see if it works. If sizeof() really does return things in terms of bits, when I had these two elements, shouldn't it return 16 instead of 8? Since long long is 8 bytes in C++ and I have two elements?
int main()
{
long long whatever[] = {0};
std::cout << whatever[0] << std::endl;
whatever[2] = 10;
std::cout << "The size of this array is " << sizeof(whatever[0] + whatever[2]) << std::endl;
}
You are not measuring the size of an array, but the size of the sum of two long longs. I.e.,
sizeof(whatever[0] + whatever[2])
is essentially the same as
sizeof(long long)
which you point out is 8.
This is undefined behavior
long long whatever[] = {0};
std::cout << whatever[0] << std::endl;
whatever[2] = 10; // BAD
The code statically initializes whatever as an array of one element. Then you assign a value to whatever[2]. The only valid index in that array is 0. Assigning anything to index 1 or 2 overwrites the important stuff on the stack or does other nefarious things.
You probably meant:
long long whatever[2] = {0};
std::cout << whatever[0] << std::endl;
whatever[1] = 10;
std::cout << "The size of this array is " << sizeof(whatever) << std::endl;
You declared an array with one element. So the valid index for this array is 0. As a result using the value equal to 2 as an index value in this expression
whatever[2] = 10;
results in accessing memory beyond the array that invokes undefined behavior.
As for the operator sizeof then it does not evaluate its operand. It only determines the type of its operand and returns the size of an object of this type.
So this expression
sizeof(whatever[0] + whatever[2])
where you may use an invalid index for the array whatever is equivalent to the expression
sizeof( long long )
From the C++ 14 Standard (5.3.3 Sizeof)
1 The sizeof operator yields the number of bytes in the object
representation of its operand. The operand is either an expression,
which is an unevaluated operand (Clause 5), or a parenthesized
type-id.
Related
This question already has answers here:
Why does it make a difference if left and right shift are used together in one expression or not?
(3 answers)
Unexepected behavior from multiple bitwise shifts on the same line [duplicate]
(1 answer)
Why does combining two shifts of a uint8_t produce a different result?
(2 answers)
Closed last year.
I am doing the following bitwise shift in Microsoft C++:
uint8_t arr[3] = {255, 255, 255};
uint8_t value = (arr[1] << 4) >> 4;
The result of these operations confused me quite a bit:
value = 255
However, if I do the bitwise shift separately:
value = (arr[i] << 4);
value = value >> 4;
the answer is different and makes much sense:
value = 15
Can someone explain to me why this happens? I am familiar with the concepts of bitwise shift, or so I believed...
Thanks in advance!
(P.S.: It seems g++ will have the same behavior. I am probably missing some important concepts with bitwise shift. Any help is greatly appreciated!)
In this expression with shift operators
(arr[1] << 4) >> 4;
there is used the integral promotions. That is the operand arr[1] is promoted to an object of the type int and such an object can store the result of the expression arr[i] << 4.
From the C++ 14 Standard (5.8 Shift operators, p.#1)
...The operands shall be of integral or unscoped enumeration type and
integral promotions are performed. The type of the result is that of
the promoted left operand. The behavior is undefined if the right
operand is negative, or greater than or equal to the length in bits of
the promoted left operand.
Here is a demonstration program
#include <iostream>
#include <iomanip>
#include <type_traits>
#include <cstdint>
int main()
{
uint8_t x = 255;
std::cout << "std::is_same_v<decltype( x << 4 ), int> is "
<< std::boolalpha
<< std::is_same_v<decltype( x << 4 ), int> << '\n';
std::cout << "x << 4 = " << ( x << 4 ) << '\n';
}
The program output is
std::is_same_v<decltype( x << 4 ), int> is true
x << 4 = 4080
As for this code snippet
value = (arr[i] << 4);
value = value >> 4;
then in the first assignment statement the result of the shift operation is truncated.
Expression (arr[1] << 4) will implicitly promote the value of arr[1] to type unsigned int before applying the shift operation, such that the "intermediate" result will not "loose" any bits (cf, for example, the explanation in implicit conversions).
However, when you write value = (arr[i] << 4);, then this "intermediate" result will be converted back to uint_8, and in this step bits get cut off.
See the difference when you write uint8_t value = ((uint8_t)(arr[1] << 4)) >> 4;
I have come across a piece of example code that uses pointers and a simple subtraction to calculate the number of items in an array using C++.
I have run the code and it works but when I do the math on paper I get a different answer.
There explanation does not really show why this works and I was hoping someone could explain this too me.
#include <iostream>
using namespace std;
int main() {
int array[10] = {0, 9, 1, 8, 2, 7, 3, 6, 4, 5};
int stretch = *(&array + 1) - array;
cout << "Array is consists of: " << stretch << " numbers" << endl;
cout << "Hence, Length of Array is: " << stretch;
return 0;
}
From: https://www.educba.com/c-plus-plus-length-of-array/
When I run the code I get the number 10.
When I print the results of *(&array + 1) and array by
cout << *(&array+1) << endl; cout << array << endl;
I get of course two hex address's.
When I subtract these hex numbers I get 1C or 28???
Is it possible that C++ does not actually give the hex results or their translation to decimal but rather sees these numbers as addresses and therefore only returns the number of address slots remaining?
That is the closest I can come to an explanation if some one with more knowledge than I could explain this I would be very grateful.
Let's take one step back and take it step-by-step to see if it will help. Continuing from my comment, the problem you are having difficulty with is one of type.
Let's take the array iteself:
int array[10] = {0, 9, 1, 8, 2, 7, 3, 6, 4, 5};
On access, an array is converted to a pointer to the first element in the array (e.g. the address of the first element) subject to caveats not relevant here. So when you say array, you have type int *, a pointer to the first element in array.
Now what happens when I take the address of the array? (&array in)
int stretch = *(&array + 1) - array;
When you take the address of the array, the result is the same address as array, but has type int (*)[10] (a pointer-to-array-of int[10]). When you add 1 to that pointer (recall type controls pointer arithmetic), you get the address for the pointer to the next array of int[10] in memory after array -- which will be 10 int after the first element of array.
So *(&array + 1) gives you the address to the next array of int[10] after array, and then dereference is only needed for type compatibility. When you dereference an int (*)[10] you are left with int[10] -- which on access gives you the address of the first element of that array (one after the original)
Think through the types and let me know if you have further questions.
You forgot a small detail of how pointer addition or subtraction works. Let's start with a simple example.
int *p;
This is pointing to some integer. If, with your C++ compiler, ints are four bytes long:
++p;
This does not increment the actual pointer value by 1, but by 4. The pointer is now pointing to the next int. If you look at the actual pointer value, in hexadecimal, it will increase by 4, not 1.
Pointer subtraction works the same way:
int *a;
int *b;
// ...
size_t c=b-a;
If the difference in the hexadecimal values of a and b is 12, the result of this subtraction will not be 12, but 3.
When I subtract these hex numbers I get 1C or 28 ???
There must've been a mistake with your subtraction. Your result should be 0x28, or 40 (most likely you asked your debugger or compiler to do the subtraction, you got the result in hexadecimal and assumed that it was decimal instead). That would be the ten ints you were looking for.
I will try it with 5 items
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int array[] {1,2,3,4,5};
int items= sizeof(array)/sizeof(array[0]);
cout << items << endl;
int items2 = *(&array +1) - array;
cout << items2 << endl;
cout << array << endl;
cout << *(&array +1) << endl;
return 0;
}
root#localhost:~/Source/c++# g++ arraySize.cpp
root#localhost:~/Source/c++# ./a.out
5
5
0x7fe2ec2800
0x7fe2ec2814
using https://www.gigacalculator.com/calculators/hexadecimal-calculator.php to subtract the numbers from each other
I get
14 hex
20 decimal.
that fits with the 4 bytes to an integer.
thanx guys :)
this is an edit done on the 12th of december melbourne time ::
I have still had questions on this topic and something did not fit right with me about the entire route to counting array items via this code.
I found something I think is interesting and again would love to know why ( I shall try to explain it as best I can my self anyway)
*(&array + 1) is the question.
lets have a look at it.
as arrays are at there very nature in c and c++ only pointers to the first element in the array how can this work.
I shall use a small set of cout calls to see if I can find out whats happening.
#include <iostream>
using namespace std;
int main(int argc, char* argv[]){
int array[] {1,2,3,4,5,6,7,8,9,10};
int size {0};
size = *(&array + 1) - array;
cout << "size = *(&array + 1) - array = " << size << endl;
cout << "*(&array + 1) = " << *(&array + 1) << endl;
cout << "(&array + 1) = " << (&array + 1) << endl;
cout << "(array + 1) = " << (array + 1) << endl;
cout << "&array = " << &array << endl;
cout << "array = " << array << endl;
cout << "*(&array) = " << *(&array) << endl;
cout << "*(array) = " << *(array) << endl;
cout << "*array = " << *array << endl;
return 0;
}
again this is off proot in my phone so still under root with no systemd.
root#localhost:~/Source/c++# g++ arrayPointerSize.cpp
root#localhost:~/Source/c++# ./a.out
size = *(&array + 1) - array = 10
*(&array + 1) = 0x7ff6a51798
(&array + 1) = 0x7ff6a51798
(array + 1) = 0x7ff6a51774
&array = 0x7ff6a51770
array = 0x7ff6a51770
*(&array) = 0x7ff6a51770
*(array) = 1
*array = 1
we see that as a pointer array can be called with * too derefernce the pointer and give the variable held in position [0] in the array.
when calling &array or reference too array we get the return of the address at the first position in the array or [0].
when calling just array we also get the address for the first position in the array or [0].
when calling *array the * is working as it does for pointers and it is dereferencing the arrays first position [0] to give the variable.
now things get a little interesting.
*(array) also dereferences the array as is seen by its value being given as 1 in this instance.
yet *(&array) does not dereference the array and returns the address to the first position in the array.
in this instance memory address 0x7ff6a51770 is the first spot in the array array = 0x7ff6a51770
and &array (reference to the pointer of the position in memory that is the first spot in the array) gives the same address 0x7ff6a51770.
it is also of note in this instance to remind us of the fact that *(&array) is also returning the first possition in the array and *(array) is not
so we can not dereference a pointer too a position in memory as its variable is the position in memory.
if array and &array give the same answer as array is a pointer too the memory position in the first spot in our array and a reference to
this pointer.
why the different answer for (array + 1) and (&array + 1).
we get the memory address 0x7ff6a51774 for (array + 1) which is in line with an integer taking four bytes on my linux or
the addition of four bytes in memory past the first spot in the array (second array spot) but (&array + 1) gives a different answer.
if we follow the bytes and the code we see that (&array + 1) actually gives us the memory address four bytes after the end of the array.
so pointer too memory address add one gives the amount of bytes the variable type is past the memory address for the start of the array
and the reference to the pointer too the memory address add one gives the address the amount of bytes the variable type is after the last ?? spot in the array.
how then can array and &array return the same answer if (array + 1) and (&array + 1) do not.
it seems to me that the & reference when working with arrays overloads the + operator when doing arithmatic.
this would explain the difference in answers as straight &array has no operator too overload so returns the same answer as calling for
straight array
this small peice of code also shows that the use of pointers using *(&array + 1) is a very bad way to show a way to find array size with
pointers as really arrays are pointers and *(&array + 1) and (&array + 1) give the same result.
the heavy work was really being done by the reference operator &.
I may still be missing something here as I have used cout directly with the different experssions and being a stream it may
be limited in its ability to take advantage of what the reference operator is really doing when working with arrays.
I am still learning this language but I shall for sure keep this in mind as I dive deaper into c++.
I believe other than a few other trials with variables that the true answer will be found when reading the source for GCC g++.
I am not ready for that yet.
I was learning how to find the length of an array and I'm baffled by this solution. I tried to find an explanation online but there seems to be none.
int arr[5] = {5, 8, 1, 3, 6};
int len = *(&arr + 1) - arr;
cout << "The length of the array is: " << len;
The memory address of the array is the same as the memory address of the first element, and when you add to or subtract from a pointer, it is done by the size of the type it points to, so:
arr refers to int, and &arr refers to int[5].
&arr+1 increments the memory address in the size of five integers.
If you do (&arr+1)-arr you get a compile error, because they are different types.
If you do (&arr+1)-&arr you get 1, because the offset of the memory address is the same as one size of int[5].
Therefore, when you do *(&arr+1), you get the same memory address but pointing to int and not int[5]. Now you wont get a compile error, because both pointers point to int and you get the offset of the memory address in terms of int size, and not int[5].
Memory addresses and types are quite difficult to explain sometimes, I hope I made it clear. Here you have some code you can run to see some of the concepts mentioned:
int arr[5] = {5, 8, 1, 3, 6};
int len = *(&arr + 1) - arr;
cout << "arr: " << arr << endl;
cout << "arr + 1: " << arr+1 << endl;
cout << "&arr: " << &arr << endl;
cout << "&arr + 1: " << &arr+1 << endl;
cout << "*(&arr + 1): " << *(&arr+1) << endl;
// cout << "&arr + 1 - arr: " << &arr+1-arr << endl;
// error: invalid operands of types ‘int (*)[5]’ and ‘int [5]’ to binary ‘operator-’
cout << "The length of the array is: " << len;
The type of the array arr is int[5], the type of &arr is int(*)[5]. (&arr + 1) increases the array address on sizeof(int[5]) as it's done by the rules of the pointer arithmetic, i.e. computes the address after the array. *(&arr + 1) is int[5], an array right after arr, where arr[5] would place. The both arguments of the substractions decay to int*. The substraction of pointers to int gives 5.
This may be considered as undefined behavior, since substraction of pointers belonging to different object storages is not defined. Also results of expressions with pointers addressing unallocated memory (like the (&arr + 1)) are undefined.
First, the traditional way to get the size of an array is sizeof a/sizeof *a. C++11 adds std::extent<decltype(a)>::value. There is of course no way to get an array’s size from just a pointer to it, as in
void f(int x[]) {/* no size here */}
Since an array is not a suitable operand to -, the array-to-pointer conversion occurs for the right-hand operand, producing an int*. Both operands must be of this type for the subtraction to result in a number of ints. &arr is of course a pointer to the array (of type int(*)[5], which conveys the size), and so therefore is &arr+1. Adding a * (or, equivalently, writing (&arr)[1]) produces an lvalue that supposedly refers to “the next array after arr”, which itself decays to a pointer that works with -.
However, as the indexing form indicates, this involves referring to an array that does not exist and is thus undefined behavior.
I defined an struct based on bytes, with size of 3 bytes. (1 packetID and 2 packetSize) I checked the size with sizeof function, and it works well:
#pragma pack(1)
typedef struct ENVIRONMENT_STRUCT{
unsigned char packetID[1];
unsigned char packetSize[2];
}
I created a variable and reserved memory like this:
ENVIRONMENT_STRUCT * environment_struct = new ENVIRONMENT_STRUCT();
For now I want to initialize environment_struct.
The problem is about I am trying to initialize this struct by attribute, just like this:
*environment_struct->packetSize = 100;
But when I checked this value, using:
std::cout << "Packet Size: " << environment_struct->packetSize << endl;
Result: Packet Size: d
Expected result: Packet Size: 100
If i will work with numbers, Should I define the struct using csdint library? For example, u_int8 and this type of variable.
When you do
ENVIRONMENT_STRUCT * environment_struct = new ENVIRONMENT_STRUCT();
you initialize packetSize to be {0, 0}. Then
*environment_struct->packetSize = 100;
turns the array into {100, 0}. Since the array is a character array when you send it to cout with
std::cout << "Packet Size: " << environment_struct->packetSize << endl;
it treats it as a c-string and prints out the string contents. Since you see d that means your system is using ascii as the character 'd' has an integer representation of 100. To see the 100 you need to cast it to an int like
std::cout << "Packet Size: " << static_cast<int>(*environment_struct->packetSize) << endl;
Do note that since packetSize is an array of two chars you can't actually assign a single value that takes up that whole space. If you want this then you need to use fixed width types like
typedef struct ENVIRONMENT_STRUCT{
uint8_t packetID; // unsigned integer that is exactly 8 bits wide. Will be a compiler error if it does not exist
uint16_t packetSize; // unsigned integer that is exactly 16 bits wide. Will be a compiler error if it does not exist
};
int main()
{
ENVIRONMENT_STRUCT * environment_struct = new ENVIRONMENT_STRUCT();
environment_struct->packetSize = 100;
std::cout << "Packet Size: " << environment_struct->packetSize << std::endl;
}
Let's first consider what *environment_struct->packetSize = 100; does. It sets the first byte of ENVIRONMENT_STRUCT::packetSize to 100. A more conventional syntax to do this is: environment_struct->packetSize[0] = 100.
There's really no way to initialize the struct in a way for the expression std::cout << environment_struct->packetSize to result in the output of 100. Let us consider what that does. environment_struct->packetSize is an array, which in this case decays to a pointer to first element. Character pointers inserted into character streams are interpreted as null terminated character strings. Luckily, you had valueinitialized the second byte of environment_struct->packetSize, so your array is indeed null terminated. The value of the first byte is interpreted as an encoded character. On your system encoding, it happens that d character is encoded as value 100.
If you wish to print the numeric value of the first byte of environment_struct->packetSize, which you had set to 100, you can use:
std::cout << "Packet Size: " << (int)environment_struct->packetSize[0] << endl;
You get this result as you tries to print a character symbol not an integer.
To fix it just cast the value or declare it as integer depending on your needs.
Cast example:
std::cout << "Packet Size: " << static_cast<int>(*environment_struct->packetSize) << std::endl;
As packetSize is declared as char-type, it's being output as a character. (ASCII code of character 'd' is 100...)
Try casting it to an integer-type:
std::cout << "Packet Size: " << (int)environment_struct->packetSize << endl;
Alternatively, since you appear to want to store the number as a 2-byte type, you could avoid such casting and simply declare packetSize as unsigned short. This will be interpreted by cout as an integer-type.
#include <iostream>
using namespace std;
int main() {
bool *a = new bool[10];
cout << sizeof(bool) << endl;
cout << sizeof(a[0]) << endl;
for (int i = 0; i < 10; i++) {
cout << a[i] << " ";
}
delete[] a;
}
The above code outputs:
1
1
112 104 151 0 0 0 0 0 88 1
The last line should contain garbage values, but why are they not all 0 or 1? The same thing happens for a stack-allocated array.
Solved: I forgot that sizeof counts bytes, not bits as I thought.
You have an array of default-initialized bools. Default-initialization for primitive types entail no initialization, thus they all have indeterminate values.
You can zero-initialize them by providing a pair of parentheses:
bool *a = new bool[10]();
Booleans are 1-byte integral types so the reason you're seeing this output is probably because that is the data on the stack at that moment that can be viewed with a single byte. Notice how they are values under 255 (the largest number that can be produced from an unsigned 1-byte integer).
OTOH, printing out an indeterminate value is Undefined Behavior, so there really is no logic to consider in this program.
sizeof(bool) on your machine returns 1.
That's 1 byte, not 1 bit, so the values you show can certainly be present.
What you are seeing is uninitialized values, different compilers generate different code. On GCC I see everything as 0 on windows i see junk values.
generally char is the smallest byte addressable- even though bool has 1/0 value- memory access wise it will be a char. Thus you will never see junk value greater than 255
Following initialization (memset fixes the things for you)
#include <iostream>
using namespace std;
int main() {
bool* a = new bool[10];
memset(a, 0, 10*sizeof(bool));
cout << sizeof(bool) << endl;
cout << sizeof(a[0]) << endl;
for (int i = 0; i < 10; ++i)
{
bool b = a[i];
cout << b << " ";
}
return 0;
}
Formally speaking, as pointed out in this answer, reading any uninitialized variable is undefined behaviour, which basically means everything is possible.
More practically, the memory used by those bools is filled with what you called garbage. ostreams operator<< inserts booleans via std::num_put::put(), which, if boolalpha is not set, converts the value present to an int and outputs the result.
I do not know why you put a * sign before variable a .
Is it a pointer to point a top element address of the array?