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.
Whenever I am writing this following code, I am getting garbage(unexpected) output in some online compiler, but if I use code block then getting satisfied output. So my question is why I am getting this type of output?
for example, if I input
5 7
+ 5
- 10
- 20
+ 40
- 20
then I am getting
22 1
in the code block. But in the online compiler, it's something else.
#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
int have, n, i;
int kid=0;
cin>>n>>have;
int line[n];
for(i=0;i<n;i++)
{
cin>>line[i];
if(line[i]>=0)
have+=line[i];
else
{
if(have>=abs(line[i]))
have+=line[i];
else
kid++;
}
}
cout<<have<<" "<<kid<<endl;
}
The main problem I can see in your code is this:
int line[n];
This is known as a VLA (Variable Length Array) and it is not supported in C++. It is valid in C. Most compilers still allow this behaviour due to the fact that C++ is based on C, but it is not valid C++ code. In a previous question, I found out that clang supports designated initializers, when gcc and vc++ did not. The reason is because some compilers like clang, support c99-extensions by default. My point is that just because the code compiles, it doesn't mean it's always right.
If you compile with the -pedantic argument, you will see that the compiler is warning you about this being a C99 feature. Have a look at the rextester example here. From the comments below, using -pedantic-errors in the compiler flags, will prompt an error.
If you know the size of the array before run-time, then you should use a static array int line[4];, but if you don't then you need to use a dynamic array. std::vector is essentially a dynamic array that also handles memory for you. It's easy to use and very efficient. std::vector<int> line;
You can read more about the vector container here: http://www.cplusplus.com/reference/vector/vector/
Btw, I tried your code in rextester, ideone and repl.it and I got the same results: 22 1. I think what you are witnessing it undefined behaviour.
Also, you can qualify int n with constexpr and it'll be fine.
constexr int n = 200;
int line[n]; //now it's ok.
But this again means that you know the size of the array at compile time.
[SOLVED]
I'm using CodeBlocks (C++) on Win10. I tried to create a simple graphic program - I downloaded a certain graphics package (graphics.h and other two files related to BGI - I added the lib in settings etc.). I tried this program but there seems to be a problem at the line marked. I ported this from Pascal (as my teacher -yes, it's about college-, only shows us Pascal programs) in a correct manner I suppose, or at least partially. The problem is certainly with the pointers (EDIT AFTER SOLVING: it wasn't!, check my answer). I'll give more details if needed.
The Question: Where I did mistakes and how to correct them (what to write, what to add, what to delete) so that it wil work fine? If there is no mistake in the code, but I NEED some files for graphics to work on my compiler, which are the files, where to get them and where to put them?
ERROR (not quite, now's a "warning"):
deprecated conversion from string constant to 'char*' [-Wwrite-strings]
(see code a bit below)
Please read: I would BE VERY GRATEFUL for a fixed version of my program. Refferences are USELESS, so unless you REALLY want to help me (thank you!), leave this page. My only related capacity is to compare two versions of a program that are intended to do the same thing but one has a mistake (or more).
CODE (updated!):
#include<iostream>
#include<graphics.h>
#include<conio.h>
using namespace std;
int main(){
int gr,xmax,ymax,r;
int gm,gd;
gd=DETECT;
gm=0;
initgraph(&gd, gm, "C:\\TC\\BGI"); /*edit(solved): followed the tutorial linked in my answer; not a directory in my PC.*/
gr=graphresult();
if(gr!=grOk) cout<<"Error!";
else {xmax=getmaxx();
ymax=getmaxy();
cout<<"Resol.: "<<xmax+1<<"x"<<ymax+1;}
setcolor(7);rectangle(0,0,xmax,ymax);setcolor(5);line(0,0,xmax,ymax);line(0,ymax,xmax,0);setcolor(3);
for(r=(ymax+1)/2;r>=0;r--) circle((xmax+1)/2,(ymax+1)/2,r);
getch();
closegraph();
return 0;
}
graphics.h source and guide: http://www.codewithc.com/how-to-include-graphics-h-in-codeblocks/
You get an error because you try to take the address of something that isn't stored in memory.
Character literals like ' ' are basically translated into integers by the compiler, and you would not expect e.g. &32 (the ASCII code for space) to work would you?
If you're supposed to pass a string, use double-quotes and no address-of operator, as in " ".
Just read your edited question and want to mention about LValue:
"LValue" means something which has an address i.e. you may apply the address operator &. LValue because it may appear on Left side of an assignment.
A variable has an address and thus is an LValue.
A character constant (e.g. 'A') has actually type int and is not an LValue.
A string constant (e.g. "Hello") has type const char[] (compatible to const char*) is (may be surprisingly) an LValue because the compiler must allocate data storage for it somewhere.
Thus, even the following would "work":
#include <stdio.h>
int main()
{
char *sz = "Hello";
printf("address of \"%s\": %p\n", sz, sz);
printf("address of sz: %p\n", &sz);
sz[0] = 'h';
printf(sz);
return 0;
}
I compiled and tested with gcc and cygwin (on Windows 10 - 64 bit):
$ gcc -o test-cstringlvalue test-cstringlvalue.c
$ ./test-cstringlvalue.exe
address of "Hello": 0x403060
address of sz: 0x61cc6c
Segmentation fault (core dumped)
So you see two important things:
It compiles fine. (Changing an LValue is not suspected by the compiler.)
It crashs because a constant string has been modified.
(It probably will not crash on any platform.)
However, I recommend not to modify string constants but it demonstrates what I tried to explain about LValues.
I hope the sample does not confuse you any more. I warmly recommend to get a good C book. There are a lot of tricks possible in C but the language itself is tricky.
Edit:
Reading my own text again I felt a little bit uncertain if I told it exactly right: Thus I googled again and found this link: SO: Why are string literals l-value while all other literals are r-value?.
I fixed the obvious syntax errors and marked the places by comment `/* <-- FIXED */:
#include<iostream>
#include<graphics.h>
#include<conio.h>
using namespace std;
int main()
{
int gr,xmax,ymax,r;
int gm,gd; /* <-- FIXED */
gd=DETECT;
gm=0;
initgraph(&gd, &gm, "C:/Users/MyName/Desktop/WORKFOLDER/"); /* <-- FIXED */
gr=graphresult();
if(gr!=grOk) cout<<"Error!";
else {
xmax=getmaxx();
ymax=getmaxy();
cout<<"Resol.: "<<xmax+1<<"x"<<ymax+1;
}
setcolor(7);rectangle(0,0,xmax,ymax);setcolor(5);line(0,0,xmax,ymax);line(0,ymax,xmax,0);setcolor(3);
for(r=(ymax+1)/2;r=0;r--) circle((xmax+1)/2,(ymax+1)/2,r);
getch();
closegraph();
return 0;
}
Unfortunately, I cannot compile and test it. (I don't have BGI libs and don't want to install it.)
Solved!
Downgraded CB (v16 to v13 I think, not sure if it was necessary) and replaced some files.
I followed this tutorial:
https://m.youtube.com/watch?v=FxCdMM9H66I
It was quite the same as the link in the question but probably (one or more of) those files (graphics.h, winbgim.h, libbgi.a) from the previous link were bugged, had some unobvious errors or so, or were incompatible etcetera), while the files given by the maker of the vid I provided in this answer were corrected. I don't (really want to) know.
Now, the warning still appears, BUT the program runs perfectly!
I replaced r=0 with r>=0 , this was a minor mistake. (I'll update the question if I still can)
Thanks for... your help! (Can't say "nothing", I'd be mean)
:)
EDIT:
Some "cleaner" version that shows the circle (just realised the variant in the question doesn't display the filled circle):
#include<iostream>
#include<graphics.h>
#include<dos.h>
using namespace std;
main(){
int gm,gd,gr,xmax,ymax,r;
gd=DETECT;
gm=0;
initgraph(&gd,&gm,"C:\\TC\\BGI");
gr=graphresult();
if(gr!=grOk) cout<<"Error!";
else {xmax=getmaxx();
ymax=getmaxy();
cout<<"Res.: "<<xmax+1<<"x"<<ymax+1;}
setcolor(7);
rectangle(0,0,xmax,ymax);
setcolor(5);
line(0,0,xmax,ymax);
line(0,ymax,xmax,0);
setcolor(3);
for(r=(ymax+1)/2;r>=0;r--) circle((xmax+1)/2,(ymax+1)/2,r);
getch();
closegraph();
}
EDIT2:
Downgrading not necessary CONFIRMED! :D
The warning should go away if you replace the literal with an array that can be converted to char*:
char driver[] = "";
initgraph(&gd, &gm, driver);
This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 7 years ago.
During study in C++ at school, when we learn about operator ++ in C++, we know ++c and c++ are different.
When we test more about this with this kind of code:
#include <iostream>
using namespace std;
int main(){
int c=10;
cout<<++c<<" "<<c++<<endl;
return 0;
}
Why did above code gave output of 12 and 10 in C++?
The computer (we tests with both cout and printf, we also tried VC++ and g++) give this to me:
12 10
Both "cout" and "printf" gave the same result.
But when we test in calculation, the result is all right.
#include <iostream>
using namespace std;
int main(){
int c=10;
int r=++c^c++;
cout<<r<<endl;
return 0;
}
Above source code gave me 0 which means while above XOR operation executing, both left hand side (++c) and right hand side (c++) giving the same value to XOR operator which is 11 (We get the value 11 by replacing c++ with 11 and computer gives the same result 0).
This is really wired. Did anyone noticed this?
By the way, we test in both debug mode and release mode in both Windows and Lubuntu. So we think this is relating to the standard library. But we aren't expecting that we can read the stdlib as a NOOB. So hoping someone can find a reason or solution.
The code int r=++c^c++; is undefined behaviour and should not be used, not ever. You can't modify the variable twice before sequence point.
This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 7 years ago.
I have here an equation i can't understand how c++ process this. Can someone explain this operation?
code:
#include <stdio.h>
main(){
int a[10] = {0,1,2,3,4,5,6,7,8,9};
int i = 0;
int num = a[i+++a[++i]]+a[++i+i++];
printf("\nnum1: %d i: %d,num,i);
}
why is the answer num = 9 while index i is just equal to 4;
Using ++ twice in the same expression on the same variable is explicitly undefined by all versions of both the C and C++ standards, and so i does not necessarily equal 4. It could be anything at the whim of the compiler writer.
Never do this. Never use ++ and -- twice in the same expression. There is no way to make any statement about what the resultant value will be, and no experience with what it does with one compiler will mean anything with respect to what another compiler does.