This question already has answers here:
Does new[] call default constructor in C++?
(4 answers)
Closed 8 years ago.
I need to create a bool array with an unknown length passed by parameter. So, I have the following code:
void foo (int size) {
bool *boolArray = new bool[size];
for (int i = 0; i < size; i++) {
if (!boolArray[i]) {
cout << boolArray[i];
}
}
}
I thought that a boolean array was initializing with false values...
Then, if I run that code in Eclipse (on Ubuntu), it works fine for me, the function prints all the values because !boolArray[i] return true (but the values are not false values, they are garbage values). If I run it in Visual Studio, the values are garbage values too, but the function does not print any value (because !boolArray[i] returns false). Why the array values are not false values by default?!? And why !boolArray[i] returns false in Visual Studio but it returns true in Eclipse?!?
I read this question: Set default value of dynamic array, so if I change the code like the following, it works fine for me too (in Eclipse and in Visual Studio)! But I have no idea why.
void foo (int size) {
bool *boolArray = new bool[size]();
for (int i = 0; i < size; i++) {
if (!boolArray[i]) {
cout << boolArray[i];
}
}
}
Sorry for my bad English!
Thanks in advance!
Adding the () for a POD instantiation, invokes value initialization in C++03 and later. In C++98 it invoked default initialization. But both reduce to zero initialization for POD types, and for booleans zero is false.
E.g., if S is a POD struct, and you have a variable
S o;
then you can zero it by doing
o = S();
No need for unsafe and ugly memset.
By the way, std::vector<bool> is a higher level alternative to your raw array of bool, but due to what's now seen as premature optimization it has a bit odd behavior: it supports an implementation with each boolean value represented by a single bit, and so dereferencing an iterator doesn't give you a reference to a bool as one might expect from general std::vector. So a better alternative is e.g. std::vector<My_bool_enum>, with My_bool_enum properly defined. Or just std::vector<char>. ;-)
Regarding
“And why !boolArray[i] returns false in Visual Studio but it returns true in Eclipse?!?”
It's just that Visual C++ chooses efficiency, not initializing where it doesn't have to, while the compiler used in Eclipse (presumably g++) does initialize even though it doesn't have to and isn't requested to do.
I prefer the Visual C++ behavior here for two reasons:
A main idea in C++ is that you don't pay for what you don't use, and the Visual C++ behavior here is in line with that idea.
Zero-initialization can easily give users the false impression that their code works, when in fact it's not portable.
Related
This question already has answers here:
Why is it that we can write outside of bounds in C?
(7 answers)
Is accessing a global array outside its bound undefined behavior?
(8 answers)
Undefined, unspecified and implementation-defined behavior
(9 answers)
Closed 11 months ago.
I wrote a code for entering element and displaying the array at the same time. The code works but since char A[4] is static memory why does not it terminate/throw error after entering more than four elements? Code:
#include <iostream>
using namespace std;
void display(char arr[],int n)
{
for(int i=0; i<n; i++)
cout<<arr[i]<<" ";
return;
}
int main()
{
char A[4];
int i=0;
char c;
for(;;)
{
cout<<"Enter an element (enter p to end): ";
cin>>c;
if(c=='p')
break;
A[i]=c;
i++;
display(A,i);
system("clear");
}
return 0;
}
Writing outside of an array by using an index that is negative or too big is "undefined behavior" and that doesn't mean that the program will halt with an error.
Undefined behavior means that anything can happen and the most dangerous form this can take (and it happens often) is that nothing happens; i.e. the program seems to be "working" anyway.
However maybe that later, possibly one million instructions executed later, a perfectly good and valid section of code will behave in absurd ways.
The C++ language has been designed around the idea that performance is extremely important and that programmers make no mistakes; therefore the runtime doesn't waste time checking if array indexes are correct (what's the point if the programmers never use invalid ones? it's just a waste of time).
If you write outside of an array what normally happens is that you're overwriting other things in bad ways, possibly breaking complex data structures containing pointers or other indexes that later will trigger strange behaviors. This in turn will get more code to do even crazier things and finally, some code will do something that is so bad that even the OS (that doesn't know what the program wants to do) can tell the operation is nonsense (for example because you're trying to write outside the whole address space that was given to the process) and kills your program (segfault).
Inspecting where the segfault is coming from unfortunately will only reveal what was the last victim in which the code is correct but that was using a data structure that was corrupted by others, not the first offender.
Just don't make mistakes, ok? :-)
The code works but since char A[4] is static memory why does not it terminate/throw error after entering more than four elements?
The code has a bug. It will not work correctly until you fix the bug. It really is that simple.
I am using fftw for a fourier transform in c++. There is the standard data type fftw_complex, which is basically a double[2]. I want to make an array of fftw_complex. I do this with
typedef fftw_complex fftw_complex_16[65536];
I set everything to zero in the array. Then I have another function which should check if an fftw_complex_16 is empty.
bool is_empty_fftw_complex_16(fftw_complex_16 *thecomplex){
std::cout<<"Test\n"<<::vowels["a:"][0][0]<<std::endl;
for (unsigned long i=0; i<65536; i++){
if(thecomplex[i][0] != 0 || thecomplex[i][1] != 0){
std::cout<<"Huch!"<<i<<std::endl;
std::cout<<thecomplex[i][0]<<" -- "<<thecomplex[i][1]<<std::endl;
std::cout<<*thecomplex[i][0]<<" -- "<<*thecomplex[i][1]<<std::endl;
return 1;
}
}
return 0;
}
Forget about the couts, they are only for debugging. The only thing the function should do is return true if the array the pointer argument points to is empty and false otherwise. It does not work. The function says the array is not empty when it is! Please help, what am I doing wrong?
The problem seems to be this
bool is_empty_fftw_complex_16(fftw_complex_16 *thecomplex){
which from your description should really be this
bool is_empty_fftw_complex_16(fftw_complex *thecomplex){
but it's hard to be completely sure because you didn't post the code which sets up this array and calls this function, which unfortunately is a crucial thing to miss out.
Something like this would be the correct way to call the function
fftw_complex_16 array;
...
is_empty_fftw_complex_16(array);
I'm guessing that you combined the incorrect declaration above with this incorrect call.
fftw_complex_16 array;
...
is_empty_fftw_complex_16(&array);
This compiles but doesn't do what you wanted.
I've been using C/C++ for about three years and I can't believe I've never encountered this issue before!
This following code compiles (I've just tried using gcc):
#include <iostream>
int change_i(int i) {
int j = 8;
return j;
}
int main() {
int i = 10;
change_i(10);
std::cout << "i = " << i << std::endl;
}
And, the program prints i = 10, as you might expect.
My question is -- why does this compile? I would have expected an error, or at least a warning, saying there was a value returned which is unused.
Naively, I would consider this a similar case to when you accidentally forget the return call in a non-void function. I understand it's different and I can see why there's nothing inherently wrong with this code, but it seems dangerous. I've just spotted a similar error in some very old code of mine, representing a bug which goes back a long time. I obviously meant to do:
i = change_i(10);
But forgot, so it was never changed (I know this example is silly, the exact code is much more complicated). Any thoughts would be much appreciated!
It compiles because calling a function and ignoring the return result is very common. In fact, the last line of main does so too.
std::cout << "i = " << i << std::endl;
is actually short for:
(std::cout).operator<<("i =").operator<<(i).operator<<(std::endl);
... and you are not using the value returned from the final operator<<.
Some static checkers have options to warn when function returns are ignored (and then options to annotate a function whose returns are often ignored). Gcc has an option to mark a function as requiring the return value be used (__attribute__((warn_unused_result))) - but it only works if the return type doesn't have a destructor :-(.
Ignoring the return value of a function is perfectly valid. Take this for example:
printf("hello\n");
We're ignoring the return value of printf here, which returns the number of characters printed. In most cases, you don't care how many characters are printed. If compilers warned about this, everyone's code would show tons of warnings.
This actually a specific case of ignoring the value of an expression, where in this case the value of the expression is the return value of a function.
Similarly, if you do this:
i++;
You have an expression whose value is discarded (i.e. the value of i before being incremented), however the ++ operator still increments the variable.
An assignment is also an expression:
i = j = k;
Here, you have two assignment expressions. One is j = k, whose value is the value of k (which was just assigned to j). This value is then used as the right hand side an another assignment to i. The value of the i = (j = k) expression is then discarded.
This is very different from not returning a value from a non-void function. In that case, the value returned by the function is undefined, and attempting to use that value results in undefined behavior.
There is nothing undefined about ignoring the value of an expression.
The short reason it is allowed is because that's what the standard specifies.
The statement
change_i(10);
discards the value returned by change_i().
The longer reason is that most expressions both have an effect and produce a result. So
i = change_i(10);
will set i to be 8, but the assignment expression itself also has a result of 8. This is why (if j is of type int)
j = i = change_i(10);
will cause both j and i to have the value of 8. This sort of logic can continue indefinitely - which is why expressions can be chained, such as k = i = j = 10. So - from a language perspective - it does not make sense to require that a value returned by a function is assigned to a variable.
If you want to explicitly discard the result of a function call, it is possible to do
(void)change_i(10);
and a statement like
j = (void)change_i(10);
will not compile, typically due to a mismatch of types (an int cannot be assigned the value of something of type void).
All that said, several compilers (and static code analysers) can actually be configured to give a warning if the caller does not use a value returned by a function. Such warnings are turned off by default - so it is necessary to compile with appropriate settings (e.g. command line options).
I've been using C/C++ for about three years
I can suppose that during these three years you used standard C function printf. For example
#include <stdio.h>
int main( void )
{
printf( "Hello World!\n" );
}
The function has return type that differs from void. However I am sure that in most cases you did not use the return value of the function.:)
If to require that the compiler would issue an error when the return value of a function is not used then the code similar to the shown above would not compile because the compiler does not have an access to the source code of the function and can not determine whether the function has a side effect.:)
Consider another standard C functions - string functions.
For example function strcpy is declared like
char * strcpy( char *destination, const char *source );
If you have for example the following character arrays
char source[] = "Hello World!";
char destination[sizeof( source )];
then the function usually is called like
strcpy( destination, source );
There is no sense to use its return value when you need just to copy a string. Moreover for the shown example you even may not write
destination = strcpy( destination, source );
The compiler will issue an error.
So as you can see there is sense to ignore sometimes return values of functions.
For your own example the compiler could issue a message that the function does not have a side effect so its call is obsolete. In any case it should issue a message that the function parameter is not used.:)
Take into account that sometimes the compiler does not see a function definition that is present in some other compilation unit or in a library. So the compiler is unable to determine whether a function has a side effect,
In most cases compilers deal with function declarations. Sometimes the function definitions are not available for compilers in C and C++.
This question already has answers here:
Accessing an array out of bounds gives no error, why?
(18 answers)
Closed 7 years ago.
Why this:
#include <iostream>
using namespace std;
int main() {
int a[1] = {0};
a[2048] = 1234;
cout << a[2048] << endl;
return 0;
}
does not give any compile-time error? (gcc 4.9.3)
Because this is legal C++.
You can try to dereference any pointer, even if it's not allocated by your program, you can try to access any cell of an array, even if it is out of bounds, the legality of an expression doesn't depend on the values of the variables involved in that expression.
The compiler doesn't have to run any static analysis to check whether you'll actually cause undefined behaviour or not, and shouldn't fail to compile if it assumes that you will (even when it is obvious that you will).
The problem is that you can't check all possible array access at compile-time (that would be way too expensive), so you'd have to arbitrarily draw a line somewhere (the problem being the word "arbitrarily", that wouldn't fit well in the standard).
Hence, checking that you won't cause undefined behaviour is the responsability of the programmer (or of specific static analysis tools).
Access to out of array range does not give any error
This is just because you were unlucky. :) What you can call it is "Undefined Behavior". Compiler is not doing any bound check on arrays, and what you are trying to do in statement a[2048] = 1234;is to write a memory location on stack, which is unused.
I wrote a simple code as follows:
void show(const int a[], unsigned elements);
int main()
{
show(new int[]{1, 2, 3, 45}, 4); //does not work
}
void show(const int a[], unsigned elements)
{
cout << "{ ";
for (int i = 0; i < elements; i++)
{
cout << a[i];
if (i != elements - 1)
cout << ",";
cout << " ";
}
cout << "}";
}
It should just output { 1, 2, 3, 45 }. If I include a size in the brackets
show(new int[4]{1, 2, 3, 45}, 4);
then it works. So naturally I would assume that if I write the new this way I have to specify the size (although I thought that giving it an initialization list would imply the size). But, the odd thing is that when set a breakpoint at the show function call and I run it step by step through the debugger, the program outputs everything correctly and terminates at the end of main like it should. If I don't use the debugger, it either crashes after outputting a '{' or it outputs the whole thing "{ 1, 2, 3, 45 }" and an assertion failure " Program: ... "Expression: _CrtIsValidHeapPointer(pUserData) ... "
I'm curious to know why it is behaving this way. Also, I am using Visual Studio on Windows 8.
EDIT: I am using namepsace std. Please don't comment about using namespaces or about how to better write this code. I'm solely interested in the cause of this issue.
EDIT Responding to additional question in comment.
To be quick, yes it would "still" be a pointer, and yes it compiles with clang and gcc when you add the 4.
There are a couple things going on, however, and my initial answer was a simplification. The problem is that your expression is not well-formed to begin with, so it's not clear what it should evaluate to or what the type should be. Consider
If type is an array type, all dimensions other than the first must be specified as positive integral constant expression (until C++14)converted constant expression of type std::size_t (since C++14), but the first dimension may be any expression convertible to std::size_t.
Source: http://en.cppreference.com/w/cpp/language/new
As it says, either way there must be an expression in the brackets. This makes it difficult to say whether the expression would still evaluate to a pointer. A well-formed new expression would indeed evaluate to a pointer, no matter how many dimensions it has, even if it has zero. When I say pointer here, I strictly mean the representation, not the type.
The point is that the type, at least "inside" new, is different depending on how many dimensions you have. So, whether you do
new int
new int[6]
new int[12][14]
the representation is the same (a pointer), but the type new sees is different in each case. The compiler is able to respond to the different types in new (think by analogy with function overloading). In particular, when the type is an array type, it is possible to initialize the new memory with the braced initializer list containing multiple elements.
My best guess is, since VS was accepting the brackets without an expression, it was allocating memory for either a single int or int[0]. In the former case, it was wrongly allowing you to brace initialize it as if it was an array type, and in the latter case the allocated memory was not enough anyway. Your main then wrote over a heap guard that is there to catch this sort of thing in debug mode. When this was checked at the end of main or at program termination, you saw the symptoms. The flakiness in the output was either due to different heap layouts or due to buffering in the output stream.
Original answer
Your new expression, if it was well-formed, would have scalar type, meaning that the result is a "single value". That single value is a pointer to an integer, specifically to the one at the beginning of the array you are trying to create. That is how "dynamic arrays" are represented in C++. The type system does not "know" their size.
You are trying to initialize this single pointer value with an initializer list of 4 values. This shouldn't work. I am not sure that this should compile at all. It certainly didn't compile with clang or gcc, and I'm surprised that it worked in Visual Studio.