What is the difference between these two assignments? - c++

Here is one way of assigning value to an array
char s[2][2];
s[0][0] = 1;
s[0][1] = 2;
s[1][0] = 3;
s[1][1] = 4;
cout << s[0][2];
output of this will be some garbage and it keeps changing. But strange thing happens when I do this
char s[2][2];
for (int i = 0, j = 0; i <= 2; i++){
if(i == 2)
{
j++;
i = 0;
}
if(j == 2) break;
cin >> s[j][i];
}
cout << s[0][2];
so as I give input as
1 2
3 4
the output was 3?
First of all shouldn't it complain that we are using array beyond its index and secondly why so much difference?

One of the things that makes C and C++ fast is that it doesn't check if you go past the bounds of an array.
Instead you get undefined behavior. When you trigger this, anything can happen. Your program may crash, it may appear to work properly, or it may generate strange results.

First of all shouldn't it complain that we are using array beyond its index
No. The standard does not specify that a program should complain if you use an array out of bounds. The standard specifies that the behaviour is undefined.
secondly why so much difference?
The behaviour is undefined. In both cases.

Related

Naive reverse string iteration infinite loop and/or assertion failure C++ / Visual Studio 2022

I am trying to reverse iterate through a string, but am getting assertion failure for the [] operator in the latest VS.
int foo() {
std::string s = "s";
for (int i = (s.size() - 1); i >= 0; i--) {
std::cout << s[i] << std::endl;
}
return 0;
}
Commenting out the cout line gives infinite loop warning and indeed enters infinite loop:
int foo2() {
std::string s = "s";
for (int i = (s.size() - 1); i >= 0; i--) {
//std::cout << s[i] << std::endl;
}
return 0;
}
Iterating forwards works just fine with or without anything in the for loop:
int bar() {
std::string s = "s";
for (int i = 0; i < s.size(); i++) {
std::cout << s[i] << std::endl;
}
return 0;
}
I am using the C++14 standard and the same code used to work on other compilers/older versions of VS. The same problem exists for any string size (although that should be irrelevant). I understand I could modify the code to use and dereference pointer instead of using int, but want to understand why this doesn't work anymore, why is it unsafe or incorrect, or what else am I missing. Thanks!
Commenting out the cout line gives infinite loop warning and indeed enters infinite loop
s.size() is an unsigned long so it can never be less than 0. The behavior of narrowing conversion due to assignment of unsigned long to int is implementation defined behavior though it should not be a problem when assigning unsigned long value 0 to int, at least I wouldn't think so, but who knows, MSVC does have its quirks.
It appears the compiler is smart enough to predict that there cannot be an infinite loop when this particular body of the for loop is present, which leads me to believe that an exception may be thrown when accessing the array, perhaps out of bounds access.
Using the debugger to track the value of i is your best bet to understand what is going on.
The issue was in fact originally caused by "auto" i rather than "int" i, but not properly refreshed. Auto gave i an unsigned int type, which overflowed the [] operator, or caused infinite loop turning over from zero to 18446744073709551615 once the i = 0 cycle completes and i-- is executed.
Thank you everyone for the helpful replies!
Could it be that your int defaults to being unsigned and therefore decrementing when i=0 resuts in a high value ?
As #PeteBecker mentioned, int should be signed and should not overflow. However my guess is that your actual code does not use int.

Incrementing index inside subscript operator [duplicate]

This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 2 years ago.
I was trying to make a 'smart' optimization when I stumbled upon some weird behavior, so I created a minimal example to replicate it.
In the code below, I create an array and shift elements to the left, then print the array.
The code works exactly like one would expect.
#include <iostream>
int main()
{
int array[5]{0,1,2,3,4};
for (int i = 0; i < 4; ++i)
{
array[i] = array[i + 1]; // Array becomes {1,2,3,4,4}
}
std::cout << "Printing array: ";
for (int i = 0; i < 5; ++i)
{
std::cout << array[i]; // Prints {1,2,3,4, 4}
}
std::cout << "\n";
}
Now, looking at the first for block, I thought I could spare one i increment.
So I tried to rewrite that block as follows:
for (int i = 0; i < 4;)
{
array[i] = array[++i]; // Expected: array becomes {1,2,3,4,4}
}
This does not work, however.
i is in fact updated, because the program does not loop, but the assignment does not go as expected and the terminal outputs Printing array: 01234.
Now, it might have been that the expression on the right is evaluated before the expression on the left, in which case this behavior would be explained.
However, I also tried the following reverse iteration:
for (int i = 4; i > 0;)
{
array[--i] = array[i]; // Expected: array becomes {1,2,3,4,4}
}
And it also outputs Printing array: 01234.
In both cases, I tried compiling in debug mode, in case it was some weird compiler optimization responsible for it, but the result was still the same.
Prior to C++17, it is undefined behavior,
Since C++17, we have
Order of evaluation
20) In every simple assignment expression E1=E2 and every compound assignment expression E1#=E2, every value computation and side-effect of E2 is sequenced before every value computation and side effect of E1.
So
array[i] = array[++i];
array[++i] is evaluated first, (incrementing so i)
array[i] is evaluated after, with i incremented.
So it is mostly equivalent to
++i;
array[i] = array[i]; // Noop
And for
array[--i] = array[i];
it is mostly equivalent to
array[i - 1] = array[i];
--i
You are invoking undefined behavior because the order of evaluation in an expression is unspecified. Don't read and write from/to an object in the same expression. The offending lines are:
array[i] = array[++i];
and:
array[--i] = array[i];
This was changed in the C++17 standard and if you compiled with C++17 support, you would not invoke undefined behavior.

Is this code undefined behavior due to accessing out of bound element in the first for loop?

Is this code undefined behavior due to accessing out of bound element in the first for loop?
int main() {
std::size_t length = 4;
int* a = new int[length];
for (std::size_t i = 0; i < length; )
a[i] = ++i;
for (std::size_t i = length - 1; i >= 0; i--)
std::cout << a[length - 1] << " ";
}
If shrotly, yes, it is. In this situation C++ doesn't define in which order expression must be calculated, because both sides have side effects. So one compiler can firstly calculate left side, second can calculate at first right side. But if you look at this, you can find that
a[i] = i++; // undefined behavior until C++17
So, you can use this line, only if you use C++ 17.

Why does this code in C++ give me a runtime error?

I am attempting to take char input from the user, and typecasting it to integer, such the A = 1; B = 2...Z = 26; and store it in an array.
This is the code:
#include <iostream>
using namespace std;
int main(){
char input;
int f[8];
int counter;
for(counter = 0; counter <= 8; counter++){
cin >> input;
f[counter] = (int)input - 64;
if(input == '\n') break;
}
cout << f[0] << endl; }
the if(input = '\n') break; line gives me an error. I am trying to break the loop on entering a new line. What's wrong in that? I am attempting to do this as I am taking 2 lines as input(which isn't important information here).
Why does this code in C++ give me a runtime error?
Because you don't use safe high-level facilities like std::array or std::vector instead of error-prone raw arrays.
The error you made causes undefined behaviour. int f[8]; is an array with 8 elements, indexed from 0 to 7, yet later on, in your loop your condition says counter <= 8, which includes 8. It should be counter < 8. Accessing f[8] is undefined behaviour.
Undefined behaviour means the compiler can build any behaviour into your program, including a crash with an error message.
Here's a safer, modern version of your program:
#include <iostream>
#include <array>
int main() {
std::array<int, 8> f;
for(auto&& element : f) {
char input;
std::cin >> input;
element = static_cast<int>(input) - 'A' + 1;
}
std::cout << f[0] << "\n";
}
Some changes:
Used std::array.
Replaced C-style cast with static_cast.
Used a C++11 range-based for loop. No need to hard-code the array's size in the loop condition.
Removed using namespace std;, which is almost always bad practice and which beginners should not use at all.
Removed your \n check, which will never work because std::cin >> input; disregards all whitespace. You will have to use std::getline to get the behaviour you want. In fact, you will want to do this anyway to get some actual error handling into your program.
Minimised scope of local variables.
The character A is not guaranteed to have the integer value 65. It's safer (and more readable) to write 'A'.
The program is giving you a runtime error because your Array loop is out of bounds. for(counter = 0; counter <= 8; counter++).
You should use for(counter = 0; counter < 8; counter++).
operator >> here skips whitespace by default, which includes newline characters - so you will never see one.
To avoid that you need to use cin.get(). There are other alternatives - you could use getline to read a line at a time and then parse the string you get.
Fixing your subscript out of bounds would be a good idea too, of course.

finding even numbers in the array issue (C++)

My code is to extract odd number and even number in an 1D array.
#include <iostream>
using namespace std;
int main() {
int a[6] = {1,6,3,8,5,10};
int odd[]={};
int even[]={};
for (int i=0; i < 6; i++) {
cin >> a[i];
}
for (int i=0; i < 6; i++) {
if (a[i] % 2 == 1) {
odd[i] = a[i];
cout << odd[i] << endl;
}
}
cout << " " << endl;
for (int i=0; i < 6; i++) {
if (a[i] % 2 == 0) {
even[i] = a[i];
cout << even[i] << endl;
}
}
return 0;
}
the output is:
1
3
5
2
1
6
It shows that it successfully extract odd numbers but the same method applied to the even number. It comes with an issue while the even number is 4.
Could anyone help me find the cause here? Thanks.
You've got an Undefined Behavior, so result may be any, even random, even formatted hard drive.
int odd[] = {} is the same as int odd[/*count of elements inside {}*/] = {/*nothing*/}, so it's int odd[0];
Result is not defined when you're accessing elements besides the end of array.
You probably have to think about correct odd/even arrays size, or use another auto-sizeable data structure.
First, although not causing a problem, you initialize an array with data and then overwrite it. The code
int a[6] = {1,6,3,8,5,10};
can be replaced with
int a[6];
Also, as stated in the comments,
int odd[]={};
isn't valid. You should either allocate a buffer as big as the main buffer (6 ints) or use a vector (although I personally prefer c-style arrays for small sizes, because they avoid heap allocations and extra complexity). With the full-size buffer technique, you need a value like -1 (assuming you intend to only input positive numbers) to store after the list of values in the arrays to tell your output code to stop reading, or store the sizes somewhere. This is to prevent reading values that haven't been set.
I don't understand your problem when 4 is in the input. Your code looks fine except for your arrays.
You can use std::vector< int > odd; and then call only odd.push_back(elem) whem elem is odd.