So here is the deal , I was writing a Bulls and Cows Game in C and had an interesting observation..It was that my program was outputting values without initial referencing....First look at the whole code
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
int main(){
int i,j,bulls,cows;
//int bulls = 0;
//int cows = 0;
char guess[4];
char chosenword[4] = "onea";
puts("Enter Your best guess <4 letter word>");
gets(guess);
for(i=0;i<4;i++){
if(guess[i] == chosenword[i]){
bulls++;
}
else {
for(j=0;j<4;j++){
if(chosenword[i]==guess[j]){
cows++;
}
}
}
}
printf("Bulls: %d And Cows: %d",bulls,cows);
return 0;
}
As you can see I have not initialized the variables bulls and cows to 0 but still my program outputs
some value or the other eg :
Here as you can see there are three trials..while the value of bulls changes the value of cows remains constant. Can anyone please explain the logic?
Because, other than the initialization, your variable contains some garbage value. You cannot predict what is that value.
In your code, bulls and cows are local variable in [auto]. So, compiler won't be initializing them, unless you do so explicitly in your code.
In contrast to using static or making them global.
Without initialization, using bulls++; or cows++ is creating a scenario read-before-write which may very well lead to undefined behavior. Always initialize your variables.
To avoid the issue: Please uncomment the initialization part in your code. :-)
A word of advice : Please don't use gets(). Use fgets(). Its lot safer.
Next,
char guess[4];
char chosenword[4] = "onea";
change to
char guess[5]; //to hold the terminating null character also
char chosenword[ ] = "onea"; //while initializing, you don't need to specify size explicitly.
EDIT:
In your case, cow is producing constant output because for your inputs, if condition never fails.
You need to avoid using gets() instead use fgets().
Using uninitialized variables leads to undefined behavior.
The value of uninitialized variables is undeterminate. The values you are seeing are some garbage values. So once we say UB anything might happen and explanation for it doesn't make sense.
Please initialize your local variables in order to get right outputs.
Related
From what I heard, I should allocate the memory like this in line 14:
array[i]=malloc(sizeof(char)*(strlen(buffer)+1)); I haven't added the 1 and still the code works perfect. I cant make it crash of return anything than 0. So, is the +1 needed or not? And if it is, what are the consequences going to be since my program runs smoothly?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 5
#define SIZE 512
int main(){
char *array[N];
char buffer[SIZE];
int i,j;
for(i=0;i<N;i++){
printf("Give word no.%d",i+1);
gets(buffer);
array[i]=malloc(sizeof(char)*strlen(buffer));
printf("%d",strlen(buffer));
if(!array[i]){
printf("Program will now exit.");
exit(0);
};
strcpy(array[i],buffer);
}
Tried it with both +1 and without. Same results although I've seen in tutorials that it is needed.
The +1 is needed to allocate room for the null terminator. If you don't, then you might write to the allocated array out of bounds, which is undefined behavior. What is undefined behavior and how does it work? Meaning it might seem to work just fine, to break mysteriously later on.
sizeof(char) is by definition always 1 though, so that part is not needed.
Recommendation: Use array[i] = malloc(strlen(buffer) + 1);
As a side note, whoever (book/teacher) told you to use gets should be retired and not be used as a source of learning C programming. Why is the gets function so dangerous that it should not be used?
i'm trying to get and print a string with gets and puts but i get a segmentation fault error when i use them togheter.
this is the code i'm trying to get this working. [i type the string "prova" to test it]
int main()
{
char *s;
gets(s);
puts(s);
return 0;
}
if i change "gets" with "scanf" i get the same error.
if i change "puts" with "printf("%s", s)" i get the output.
if i declare char *s = "prova" and then puts(s) i get the output.
i also tried to change char *s; with char s[] but i get the same error.
where i'm i wrong on this? ty very much
i know gets is bad, is just bc i'm writing exercise from "C how to program, fifth edition" by Deitel and Deitel
You have multiple problems with that piece of code. To start with gets have been deprecated since the C99 standard, and in the C11 standard it has been removed. The reason is that it's not very safe, and has no bounds-checking and so can write beyond the bounds of the memory you pass to it leading to buffer overflows.
Secondly, you use the uninitialized local variable s. The value of an uninitialized variable is indeterminate, and will be seemingly random. Using an uninitialized local variable leads to undefined behavior, which often leads to crashes.
Another problem is if you initialize s to point to a literal strings. Literals strings are constant (read-only) arrays of characters, and attempting to write to it will again lead to undefined behavior.
You need to allocate some room for the string:
char s[256];
gets(s);
puts(s);
But gets is bad. (It doesn't know how big your buffer is, so what happens if more than 255 characters are read?)
The most important mistake you have is that you are declaring a char pointer, but you are not reserving the space in memory where the characters will be stored, so you got a pointer that point to some random memory adress that you should'nt use. the "right" thing to do will be:
#include <stdio.h>
#include <stdlib.h>
#define LENGHT 20
int main()
{
char *s;
s=malloc(sizeof(char)*LENGHT); //here you make the pointer point to a memory adress that you can use
gets(s);
puts(s);
free (s);
return 0;
}
But also is strongly recommend to avoid using gets because that function doesn't check for the length of the input, so use fgets instead that allow you to do that, you will only need to set the data stream to stdin.
The code will be:
#include <stdio.h>
#include <stdlib.h>
#define LENGHT 20
int main()
{
char *s;
s=malloc(sizeof(char)*LENGHT);
fgets(s,20,stdin);
puts(s);
free(s);
return 0;
}
I'm a beginner in C .... I have a little code:
#include <stdio.h>
#include <string.h>
int main(){
char str1[100];
char str2[100];
char str3[100];
char str4[100];
puts(str1)
puts(str2);
puts(str3);
puts(str4);
return 0;
}
I got result
2
èý(
‘Q]wØ„ÃîþÿÿÿÀ"bwd&bw
I don't know why my array does not empty from the begin. And I have to set first element to "\0" to clear content of array. Can anyone explain for me. Thank a lot.
In C, local variables are not initialized automatically if you don't assign values to them. Here your arrays are uninitialized, which means they may contain garbage after their creation.
Yes, you need to explicitly set it to be "empty" like:
char str[100];
str[0] = '\0';
// Now you have an empty string of zero length.
assert(strlen(str) == 0);
// But the size is still 100.
printf ("%d", sizeof(str));
Alternatively, you can create an empty string(character array) during the initialization. It has the same size and length as the example above.
char str[100] = "";
As for why it doesn't automatically zero the string, it's because that would be costly to do so, and C generally doesn't do costly things that you don't explicitly tell it to do. At a minimum, it would have to set the first element of every array to zero,and there are plenty of occasions where you wouldn't want to or need to initialize the array like this. If C always did this for you, then you'd always have that useless overhead that you couldn't get rid of.
As a general rule, C doesn't do anything in the background that you don't explicitly tell it to do, so when you ask for an array, it just gives you an array, and doesn't touch the contents unless you tell it to. It can create a little bit more work for the programmer, but with the benefit of more finely-grained control over exactly what the computer is doing.
Some people would consider that it's a good programming practice to always initialize your variables anyway, and to forget about this kind of tiny cost, and a lot of the time they'll have a good point, but C is deliberately a very flexible and low-level language, and it just doesn't force you to do things like this.
one is getting old when one says "In my days...". But nevertheless, "in my days", people were instructed to first declare variables, and directly afterward initialise variables.
In your case, you can do both together and even more thoroughly in one statement.
The solution of Eric Z is the correct one, that I would also use when I'm working the C-way. But to be complete for you, what age_pan describes is that Java inherently does te following:
#include <stdio.h>
int main(int argc, const char * argv[])
{
char str1[100] = { 0 };
char str2[100] = { 0 };
char str3[100] = { 0 };
char str4[100] = { 0 };
puts(str1);
puts(str2);
puts(str3);
puts(str4);
return 0;
}
The difference is that in the solution of Eric Z only the first character is set to 0, which means that you create a zero length zero terminated string. The Java method (shown in the code above) initialises every little byte to 0.
There are pro's and con's to the Java initialisation. It leads to sloppy programming (some call it easier programming) and it takes time if you don't need initialising. On the other hand, I know very little people that need te extra milliseconds that are lost by the initialisation.
Is it necessary to declare variables above the code, and to initialise them? Certainly not. Is it useful? It most certainly is. It avoids all kinds of errors that take a lot of time to debug.
By the way, you are missing a ; after puts(str1) :-)
Kind regards,
PB
I don't think you had any trouble if the array doesn't start with "empty". In C, the variables start with random values. Unlike in Java, when you declare a variable, the JVM will initiate it by default.
#include <stdio.h>
#include <stdlib.h>
int test(void)
{
int a=0,b=0;
char buf[4];
gets(buf);
printf("a:%d b:%d",a,b);
}
int main()
{
test();
return 0;
}
Question is why with input:aaaaa a is becoming 97 instead of b?From the way variables are declared inside test when buf overflows shouldn't it affect first b and then a?
a and b variables will not be necessarily contiguous to the variable buf. Consequently, the overflow of the variable buf, has nothing to do with the possible values of a and b. The behaviour will be undefined.
However, it is important to mention that the C standard will store all of the arrays, such as buf, in continuous memory location.
Here you can check the documentation:
An array is a series of elements of the same type placed in contiguous
memory locations that can be individually referenced by adding an
index to a unique identifier.
Undefined behaviour is undefined. There's nothing in the language standard about the relative locations of different variables in a function, and there's definitely no guarantees about what will happen in a buffer overflow situation.
i was just trying to check the default value of int and char when not initialised in c.
my problem is that i get two different outputs when i use clrscr() to clear the screen between 2 runs.could someone explain this behavior to me?
here is the code
void main()
{
int i;
char c;
printf("%d %c",i,c);
}
output: 0
void main()
{
int i;
char c;
clrscr();
printf("%d %c",i,c);
}
output:-29542 //some garbage value which is what i was expecting in both cases
You shouldn't be expecting anything in particular. The values are uninitialized, i.e.: can be anything.
Why the garbage value in the first case differs from the garbage value in the second case? Who knows? Different memory map, different execution paths - different garbage.
I think it always give some garbage value ..you can't determine the behavior... :-/
In case of your code, you will get garbage values, but if the integer varibale was declared globally then its default value will be 0 for sure in C.
I mentioned this because question's title was-"Default values of int when not initialized in c".
Actually zeros were garbage as well. After you add clrscr(); you changed stack so you did to garbage.
In managed code, there are default values, usually 0 or equivalent.
In the unmanaged world, there is no default value. When the memory is allocated, the system just tells you "You can write here is you want, but I don't know what mess the previous program let behind".
This behaviour is seen for some people as bad since their program can be unpredictable for some obscure reasons, but it is also a way to be able to optimize as much as we can memory management, think of large buffer allocation which when allocated would be filled with 0s, and then filled with actual data. You get twice the performance in unmanaged code!