I have the following code:
#include<stdio.h>
int main(){
int a = 1, b = 8;
while(a != b)
{
printf("asd");
fflush(stdout);
}
return 0;
}
Clearly, the program never stops. But why is "asd" not printed at all?
EDIT: This is the complete program. There are not any other lines. The first time I used Eclipse and MinGW and it didn't print anything. I tried then with gcc in linux and it was working as expected, even without fflush!
So probably this behaviour might be caused by the fact that some compilers optimize the code and modify the infinite loops.
fflush(stdin) is meaningless, and in fact causes undefined behaviour according to the standard - you probably meant fflush(stdout). If you make that change, you'll see output.
Related
int main()
{
char ch = 0;
int c = 0;
scanf("%d", &ch);
printf("%c", ch);
}
I can input the ASCII number and output the correct character. But the program crashes at the end of the code, the } sign.
Using Visual Studio 2019
Run-Time Check Failure #2 - Stack around the variable 'ch' was corrupted.
Since scanf has non-existent type safety, it can't know the type of parameters passed (one reason why the format string is there in the first place).
The stack corruption is caused by you lying to the compiler here: scanf("%d", &ch);. You tell it "trust me, ch is an int". But it isn't. So scanf tries to store 4 bytes in an area where only 1 byte is allocated and you get a crash.
Decent compilers can warn for incorrect format specifiers.
There are multiple problems in your code:
missing #include <stdio.h> ;
unused variable c ;
type mismatch passing a char variable address when scanf() expects an int * for the %d conversion specifier ;
missing test on scanf() return value ;
missing newline at the end of the output ;
missing return 0; (implied as of c99, but sloppy).
Here is a modified version:
#include <stdio.h>
int main() {
int ch;
if (scanf("%d", &ch) == 1) {
printf("%c\n", ch);
}
return 0;
}
I guess your question was not, "What did I do wrong?", or "Why didn't it work?".
I guess your question is, "Why did it work?", or, "Why did it print an error message after seeming to work correctly?"
There are lots of mistakes you can make which will corrupt the stack. This is one of them. Much of the time, these errors are rather inscrutable: If the memory corruption is severe enough that the memory management hardware can detect it, you may get a generic message like "Segmentation violation" at the instant the bad access occurs, but if not, if the damage isn't bad enough to cause any overt problems, your program may seem to work as you expected, despite the error.
It would be prohibitively expensive to perform explicit tests (in software) to check the stack for damage during every operation. Therefore, no attempt is made to do so, and the primary responsibility is placed on you, the programmer, not to do obviously wrong things like telling scanf to store an int in a char-sized box.
In this case, your system did make a check for stack damage, but as some kind of a one-time operation, only after the main function had returned. That's why the scanf and the printf seemed to work correctly, and the error message seemed to coincide with the closing } at the end of main.
Echoing an analogy I made in a comment, this is sort of like having a policeman write you a ticket for having done something dangerous that did not cause an accident. Why not write the ticket as you are doing the dangerous thing? Why write the ticket after the fact at all, since your dangerous behavior didn't cause an accident? Well, because sometimes that's just the way the world works.
I think you are trying to input an integer and print its char value so in my opinion this is what you are trying to do:
#include <iostream>
using namespace std;
int main()
{
int c = 0;
scanf("%d", &c);
printf("%c", c);
return 0;
}
Note: This is a C++ code but the syntax inside main function will work for C language as well
I build a small program that simply copy the text from an input.txt file to an output.txt file. It works with no apparent problem with the command:
./myCopier.txt < rand.txt > randout.txt
on a GCC89 compiler, used for didactic purposes.
#include<stdio.h>
int main(void){
int c;
while ((c = getchar()) != EOF)
putchar(c);
/*The text in printf() does not appear anywhere*/
printf("My theories and toughts!\n");
}
Later, I add printf() in order to print my thoughts about how the program worked. It compiles without errors or warnings even with restrictive parameters (-Wall), but this text does not appear in any place. By any place, I mean both output.txt and the standard output.
I am thinking that:
The command ./myCopier.exe alone clearly create an endless loop. Without text input there is no EOL character, hence the print() command is never reached.
So, why when the input is provided, the printf() command has no apparent effect? I'd expect the text from printf()to appear on the standard output, just when the loop closes and output.txt is created. Why does it not occur?
My theory is that ./myCopier.txt < rand.txt > randout.txt does not allow it. For some reason, it makes the program only transfer the input to the output, "ignoring" everything does not come from the input. Am I correct? If so, why?
If you are interested in the problem with deeper detail, here is the assembly code:
http://text-share.com/view/79f31f38
Omitting the return statement in main() causes undefined behavior in C89/C90.
Normally, returning from main() forces the output buffer to be flushed. If you omit the return statement, anything can happen.
Try to add return 0 at the end of main() as was required in C90. GCC in c90/gnu90 mode will warn you otherwise: "control reaches end of non-void function".
Try to add fflush(stdout);.
I'm learning C. So I wrote this distance timer program.
It runs well with gnu-gcc compiler.
But but with gnu-gcc for avr it does compile but when I run it I get only a cmd session that does nothing except disappearing once I press any button.
I want to know why.
I am using code blocks and here is my code
#include<stdio.h>
#include<stdlib.h>
#define speedpersecond 5
int main()
{
char time [5];
double distance;
printf("Please enter time in seconds");
gets(time);
distance = atoi(time) * speedpersecond;
printf("Distance is %g ", distance);
return 8585;
}
You are probably running into the reason gets have been deprecated since the C99 standard, and removed completely in the C11 standard: Buffer overflows are way to easy.
If you give more than four characters as input then gets will write out of bounds of the array and you will have undefined behavior.
Instead use fgets to read lines in a safe way.
And regarding that return from the main function. Many systems (including all POSIX systems, like macOS and Linux) uses eight bits for the return value. Also, anything but zero is considered to be a failure by shells and calling environments.
You should also know that the atoi function have no major error checking. It's impossible to know if the string you pass contains e.g. "0" or don't have any digits at all. In both cases it will return 0. A safer function which will help you detect errors is the strtol function.
Some of the examples in K&R don't work in Code:Blocks when I type them exactly.
For example, this program:
#include <stdio.h>
main()
{
long nc;
nc = 0;
while (getchar() != EOF)
++nc;
printf("%ld\n", nc);
}
When I type this code and run it, the program either freezes or doesn't do anything when I press enter.
The program below does the same thing (count characters in a string) and it works.
#include <stdio.h>
int main()
{
char s[1000];
int i;
scanf("%s",s);
for(i=0; s[i]!='\0'; ++i);
printf("Length of string: %d",i);
return 0;
}
Am I missing something here? Has C been changed since K&R 2nd Edition or am I doing something wrong?
When you press enter, you send \n into the standard input stream(and flushes other data into the stdin,if any). This character(\n) is not the same as EOF. To send EOF, press following keys combinations:
CTRL Z and then Enter in Windows.
CTRL D in Unix/Linux/OSX
C has been changed since that book was written, but even still the code is not well-defined/valid C under any version of the standard.
If you compile using the current C standard (C11), or the previous (C99), a strictly conforming compiler (such as gcc -std=c11 -pedantic-errors) will give an error: main must return int. The old "implicit int" feature was removed in C99.
If you compile using the old C90 standard, the code invokes undefined behavior, because there is no return statement. This was allowed in C90 but it is not safe, it could cause program crashes etc. Invoking undefined behavior is always a bug, and therefore very bad practice.
(In C99, functions returning a value must have a return statement, with the exception of main(), where return can be safely omitted. So you could omit the return statement of main() if you compile as C99.)
Simply correct the code as you have already done, and it will compile in any version of the standard, without invoking undefined behavior.
Scenario 1:
Code:
int main(){
int a = 12345678;
if(isdigit(a)){
printf("ok: foo\n");
}
else{
printf("false: bar\n");
}
printf("test\n");
return EXIT_SUCCESS;
}
Output:
Segmentation fault
Scenario 2:
Code:
...
if(isdigit(a)){
//printf("ok: foo\n");
}
else{
//printf("false: bar\n");
}
printf("test\n");
...
Output:
test
and now the last, Code:
...
int a = 1234567;
...
Output:
ok: foo
test
What's wrong with isdigit()? I do not understand!
Probably because the compiler optimizes the isdigit function call from the code. That is it doesn't run it.
Also note that isdigit expects a character, not a number. http://www.cplusplus.com/reference/clibrary/cctype/isdigit/
This is because isdigit can be defined as macro like this
#define isdigit(c) ((map[c] & FLAG_DIGIT)==FLAG_DIGIT)
You call isdigit with integer value, but map array size is 256 elements. In this case you try to read value outside of array bounds -> segmentation fault. This segmentation fault can occurs randomly. Depending on your program or data size.
This was probably optimized by the compiler. As neither the if or the else does something, it was removed and the isdigit ends up not called. Be sure to
#include <ctype.h>
The segmentation fault is coming probably from the fact that you're passing a (not so small) number, when a character was expected. When you remove the printf statements and the compiler optimizes it, the call won't happen thus not failing.
Note that the headers can be in fact omitted since the program will be linked with the standard C library by default, so it works. But it's not a good idea, and you should see a warning at least.
First of all, isdigit(3) checks whether a character is a digit.
The segmentation fault probably (I'm positive) happens because you haven't included stdio.h.
Then you're calling printf which uses variable arguments without knowing its prototype (undefined behavior).