This program:
#include <stdio.h>
#include <conio.h>
int main()
{
printf("%d %d %d",1) ;
getch();
return 0;
}
gives me result 1 0 0 instead of warning or error or 1
Could you please tell me the logic behind it ?
I'm using Visual Studio 2010 to compile this code.
This is undefined behavior and not something you should rely on. While using printf () if sufficient and appropriately matching arguments are not provided, like in your case printf("%d %d %d",1), C does not define what should happen in that case and so the behavior is not standard or defined.
It is possible that this could cause your program to crash (if the next memory addresses from where printf () read values are not accessible or non-existant).
With printf(), if insufficient matching arguments are not provided, the result is undefined behavior.
C does not define what should happen in this case.
... If there are insufficient arguments for the format, the behavior is
undefined. ... C11 ยง7.21.6.1 2
OP's code obviously printed 2 additional int with the value of 0. Why 0 today - look at the compiled assembly language. Might another compilation of the code has the same result - maybe - maybe not. It is not defined by the language.
printf doesn't care if there aren't enough arguments. "doesn't care" means that it doesn't actually check the number of items in the format list to make sure that a sufficient number of arguments have been specified.
if there are not enough arguments, printf will just access computer memory (the memory that would have been used, had sufficient arguments been specified) and use whatever data is there.
this is "undefined behavior" and the results will vary. it's possible that this could cause your program to crash (if the memory at the location is inaccessible or non-existent).
you'll find that this sort of thing is very common in languages like C, where you can do things should be considered "invalid" but that are simply accepted by the compiler.
Related
For some homework I have to write a calculator in C. I wanted to input some string with scanf and then access it. But when I access the first element I get a segmentation error.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(){
char input1[30];
scanf("%s",input1);
printf("%s",input1);
char current = input1[0];
int counter = 0;
while(current != '\0'){
if(isdigit(current) || current == '+' || current == '-' || current == '*' || current == '/'){
counter++;
current = input1[counter];
}else{
printf("invalid input\n");
exit(1);
}
}
return 0;
}
The printf in line 3 returns the string, but accessing it in line 4 returns a segmentation error (tested in gdb). Why?
There are a few potential causes, some of which have been mentioned in the comments (I won't cover those). It's hard to say which one (or more) is the cause of your problem, so I guess it makes sense to iterate them. However, you may notice that I cite some resources in the process... The information is out there, yet you're not stumbling across it until it's too late. Something needs to change with how you research, because this is slowing your progress down.
On input/output dynamics, just a quick note
printf("%s",input1);
Unless we include a trailing newline, this output may be delayed (or "buffered"), which may have the effect of confusing you about the root of your issues. As an alternative to using a trailing newline (which I'd prefer, personally) you could explicitly force partial lines to be written by invoking fflush(stdout) immediately after each of the relevant output operations, or use setbuf to disable buffering entirely. I think this is unlikely to be your problem, but it may mask your problem, so it's important to realise, when using printf to debug, it might be best to include a trailing newline...
On main entry points
The first potential culprit I see is here:
int main()
I don't know why our education system is still pushing these broken lessons. My only guess is the professors learnt many years back using the nowadays irrelevant Turbo C and don't want to stay up-to-date with tech. We can further reduce this to a simple testcase to work out if this is your segfault, but like I said, it's hard to say whether this is actually your problem...
int main() {
char input1[30];
memset(input1, '\x90', sizeof input1);
return 0; // this is redundant for `main` nowadays, btw
}
To explain what's going on here, I'll cite this page, which you probably ought to go and read (in its entirety) once you're done here:
A common misconception for C programmers, is to assume that a function prototyped as follows takes no arguments:
int foo();
In fact, this function is deemed to take an unknown number of arguments. Using the keyword void within the brackets is the correct way to tell the compiler that the function takes NO arguments.
Simply put, if the linker doesn't know/can't work out how many arguments are required for the entry point, there's probably gonna be some oddness to your callstack, and that's gonna occur at the beginning or end of your program.
On input errors, return values and uninitialised access
#include <assert.h>
#include <stdio.h>
#include <string.h>
int main(void) {
char input1[30];
memset(input1, '\x90', sizeof input1);
scanf("%s",input1); // this is sus a.f.
assert(memchr(input1, '\0', sizeof input1));
}
In my testcase, I actually wrote '\x90' to each byte in the array, to show that if the scanf call fails you may end up with an array that has no null terminator. If this is your problem, this assertion is likely to throw (as you can see from the ideone demo) when you run it, which indicates that your loop is likely accessing garbage beyond the bounds of input1. On this note I intended to demonstrate that we (mostly) cannot rely upon scanf and friends unless we also check their return values! There's a good chance your compiler is warning you about this one, so another lesson is uto pay close attention to warning messages, and strive to have none.
On argument expectations for standard library functions
For many standard library functions it may be possible to give input that is outside of the acceptable domain, and so causes instability. The most common form, which I also see in your program, exists in the form of possibly passing invalid values to <ctype.h> functions. In your case, you could change the declaration of current to be an unsigned char instead, but the usual idiom is to put the cast explicitly in the call (like isdigit((unsigned char) current)) so the rest of us can see you're not stuck in this common error, at least while you're learning C.
Please note at this point I'm thinking whichever resources you're using to learn aren't working, because you're stumbling into common traps... please try to find more reputable resources to learn from so you don't fall into more common traps and waste more time later on. If you're struggling, check out the C tag wiki...
I have the following program that causes a segmentation fault.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
printf("TEST");
for (int k=0; k<(strlen(argv[1])); k++)
{
if (!isalpha(argv[1])) {
printf("Enter only alphabets!");
return 1;
}
}
return 0;
}
I've figured out that it is this line that is causing the problem
if (!isalpha(argv[1])) {
and replacing argv[1] with argv[1][k] solves the problem.
However, I find it rather curious that the program results in a segmentation fault without even printing TEST. I also expect the isalpha function to incorrectly check if the lower byte of the char* pointer to argv[1], but this doesn't seem to be the case. I have code to check for the number of arguments but isn't shown here for brevity.
What's happening here?
In general it is rather pointless to discuss why undefined behaviour leads to this result or the other.
But maybe it doesn't harm to try to understand why something happens even if it is outside the spec.
There are implementation of isalpha which use a simple array to lookup all possible unsigned char values. In that case the value passed as parameter is used as index into the array.
While a real character is limited to 8 bits, an integer is not.
The function takes an int as parameter. This is to allow entering EOF as well which does not fit into unsigned char.
If you pass an address like 0x7239482342 into your function this is far beyond the end of the said array and when the CPU tries to read the entry with that index it falls off the rim of the world. ;)
Calling isalpha with such an address is the place where the compiler should raise some warning about converting a pointer to an integer. Which you probably ignore...
The library might contain code that checks for valid parameters but it might also just rely on the user not passing things that shall not be passed.
printf was not flushed
the implicit conversion from pointer to integer that ought to have generated at least compile-time diagnostics for constraint violation produced a number that was out of range for isalpha. isalpha being implemented as a look-up table means that your code accessed the table out of bounds, therefore undefined behaviour.
Why you didn't get diagnostics might be in one part because of how isalpha is implemented as a macro. On my computer with Glibc 2.27-3ubuntu1, isalpha is defined as
# define isalpha(c) __isctype((c), _ISalpha)
# define __isctype(c, type) \
((*__ctype_b_loc ())[(int) (c)] & (unsigned short int) type)
the macro contains an unfortunate cast to int in it, which will silence your error!
One reason why I am posting this answer after so many others is that you didn't fix the code, it still suffers from undefined behaviour given extended characters and char being signed (which happens to be generally the case on x86-32 and x86-64).
The correct argument to give to isalpha is (unsigned char)argv[1][k]! C11 7.4:
In all cases the argument is an int, the value of which shall be representable as an unsigned char or shall equal the value of the macro EOF. If the argument has any other value, the behavior is undefined.
I find it rather curious that the program results in a segmentation fault without even printing TEST
printf doesn't print instantly, but it writes to a temporal buffer. End your string with \n if you want to flush it to actual output.
and replacing argv[1] with argv[1][k] solves the problem.
isalpha is intended to work with single characters.
First of all, a conforming compiler must give you a diagnostic message here. It is not allowed to implicitly convert from a pointer to the int parameter that isalpha expects. (It is a violation of the rules of simple assignment, 6.5.16.1.)
As for why "TEST" isn't printed, it could simply be because stdout isn't flushed. You could try adding fflush(stdout); after printf and see if this solves the issue. Alternatively add a line feed \n at the end of the string.
Otherwise, the compiler is free to re-order the execution of code as long as there are no side effects. That is, it is allowed to execute the whole loop before the printf("TEST");, as long as it prints TEST before it potentially prints "Enter only alphabets!". Such optimizations are probably not likely to happen here, but in other situations they can occur.
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.
The following program gives an unexpected output .
#include<stdio.h>
int main()
{
int a=10,b=20;
printf("a=%d",a);
printf(" b=%d");
printf(" %d");
return 0;
}
Why does the above code print:
a=10 b=10 10
The output is same even if I declare b before a, or make 'a' register variable.
According to this post - Behaviour of printf when printing a %d without supplying variable name, a random value from the current stack is printed. But if that was the case, then changing the declaretion styles would result in different results.
So, what is actually happening here?
Function calls are designed so that arguments are always in a pre-defined place. Some older architectures put the arguments on the stack, most new architectures put the arguments in registers.
What's happening here is that the you overwrite the first argument to all the function calls to printf, but the second argument happens to stay unmodified. It's just luck though, anything could have overwritten the place on the stack or the register where the second argument is.
This is the core of undefined behavior in C. Anything could have happened, but usually you can reason about what actually happened. And that's why undefined behavior is so dangerous. Often you end up with behavior that seems predictable and then a minor operating system update or compiler update will change the behavior completely.
put pointer to "a=%d" on the stack, put a on the stack, call printf(), reduce stack-pointer. Then put pointer to " b=%d" on the stack, call printf(), voila, a is still on the stack
When I am compiling this program I am getting some random number as output.. In Cygwin the output is 47 but in RHEL5, it is giving some negative random numbers as output.
Can anyone tell me the reason?
Code:
main()
{
printf("%d");
}
This program provokes undefined behavior since it does not follow the rules of C. You should give printf one argument per format specifier after the format string.
On common C implementations, it prints whatever happens to be on the stack after the pointer to "%d", interpreted as an integer. On others, it may send demons flying out of your nose.
It is Undefined Behaviour.
On 3 counts:
absence of prototype for a function taking a variable number of arguments
lying to printf by telling it you are sending 1 argument and sending none
absence to return a value from main (in C99 a return 0; is assumed, but your code definitely isn't C99)
Anything can happen.
printf expects a second argument, so it reads whatever happens to be on the stack at that location. Essentially it's reading random memory and printing it out.