For this code below (in C)
int small_a, small_b;
printf("Please input two numbers\n");
scanf_s("%d %d", &small_a, &small_b);
printf("%d %d", &small_a, &small_b);
int test_2nd = small_a - small_b;
if (test_2nd < 0) {
printf("a is smaller %d", &small_a);
}
else {
printf("b is smaller %d", &small_b);
The values it prints when I write 4 and 2 is a huge six digit number (5504620 and 5504608 in this case) I don't understand where it goes wrong. stdio.h has been included as a header.
The problem here is in the print statement. In the code
printf("%d %d", &small_a, &small_b);
you don't need (want) to take (print) the address. Remove that &.
That said, this actually invokes undefined behavior. %d with printf() expects an argument of type int and you're essentially supplying an int *, causing the UB.
FWIW, to print an address (pointer), you need to use %p format specifier and cast the argument to void *
Related
I took input in %d format into a character using scanf() because I didn't want more than 8 bits. But doing so changed the value of another char variable.
Code:
#include <stdio.h>
int main() {
char a;
char b;
printf("Enter a: ");
scanf("%c", &a);
printf("a = %c\n", a);
printf("Enter b: ");
scanf("%d", &b);
printf("\na = %d\n", a);
printf("b = %d\n", b);
}
Output:
Enter a: c
a = c
Enter b: 56
a = 0
b = 56
Screenshot
scanf reads data from stdin and stores them according to the parameter format into the locations pointed by the additional arguments.
scanf("%d", &b);
With %d you are storing an integer into the char variable that can not hold an integer.
the Variable now grows into the other variable in stack above it.
if you compile with the flag "-fstack-protector-all" you should get the
*** stack smashing detected *** error on execution.
The formatting directives in a scanf format string indicate not just how to match the input, but also the type of the corresponding variable in which the resulting value is to be stored. If you pass a pointer to an object of a different type than the corresponding directive expects then you reap undefined behavior.
That's true even for a simple signedness mismatch, but in your case you have a size mismatch. For a %d directive without a size modifier, scanf expects to write the scanned integer value in an object of type [signed] int. If the pointer you pass instead points to a char, and if, as is the case in most implementations, int is larger than char, then it is particularly likely that the resulting undefined behavior manifests in unwanted ways, such as by producing changes in the values of other variables.
If you want to scan a number as a char-sized integer, then you should
Declare the variable as either signed char or unsigned char, not default char, and
Use the correct conversion specifier and size modifier for the chosen data type.
For example,
unsigned char b;
scanf("%hhu", &b);
%u is the format directive for an unsigned integer, and the hh modifier instructs scanf that the destination variable is the size of a char / signed char / unsigned char.
If you want a signed integer then it would be similar, but with the %d formatting directive:
signed char b;
scanf("%hhd", &b);
As a matter of style, do not use default char for numeric data, even if you are confident that the range of values you need to support is a subset of the intersection of the ranges of signed char and unsigned char. Especially so if you plan to use it with formatted I/O functions, because it is implementation-specific whether %hhd or %hhu is the correct directive for a default char.
I agree with the side effect you indicated. This happens when the compiler loads variables in memory one after the other. For example, I examined the change in variable a when a sufficiently large number is typed in variable b. I changed the code as follows.
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
char a, b;
printf( "Address (a): %p\tAddress(b): %p\n", &a, &b);
printf( "Enter the values (a, b): " );
scanf( "%c, %d", &a, &b);
printf( "Value (a): %d\tValue (b): %d\n", a, b);
return EXIT_SUCCESS;
}
Then, when I tested the code, I realized the consequences of this side effect.
The tested code is interpreted in the image below.
This is C. So trying to put multiple inputs into this array and keep getting numbers like this for when output the input 6356740 "6356744 6356748 6356752"
#include <stdio.h>
#include <stdlib.h>
int main()
{
int quiz[4];
printf("Enter four quiz grades: ");
scanf("%d %d %d %d", &quiz[1], &quiz[2], &quiz[3], &quiz[4]);
printf("%d %d %d %d", &quiz[1], &quiz[2], &quiz[3], &quiz[4]);
}
An array with K elements is indexed from 0 to K-1.
(This is mentioned in any introduction to arrays.)
Reading or writing quiz[4] has undefined behaviour.
You should not pass pointers to printf if you want to print integers.
int main()
{
int quiz[4];
printf("Enter four quiz grades: ");
scanf("%d %d %d %d", &quiz[0], &quiz[1], &quiz[2], &quiz[3]);
printf("%d %d %d %d", quiz[0], quiz[1], quiz[2], quiz[3]);
return 0;
}
You defined your array as
int quiz[4] which means the first reference is quiz[0], the second is quiz[1], the third is quiz[2] and the last is quiz[3].
In your code you are referencing the 2nd, 3rd, 4th and undefined 5th entry. This is important as you may be corrupting the data in your program which can caused undefined results.
The numbers you are seeing are the integer values of the addresses pointing to the ints in your array. Notice they increase by 4 which is the size of an int.
Also, your printf is printing the addresses of the int and not the ints themselves. The line should read
printf(“%d %d %d %d”, quiz[0], quiz[1], quiz[2], quiz[3]);
If the grades being input are numbers, that '%d' in all four places is okay. But if you are entering alphabets, than you should be using '%s' instead.
And as Hogstrom and molbdnilo said, the first entry of a Array is 0, than second is 1, and so on. Hence you have to use &quiz[0] than &quiz[1] .. and so on.
I've had this problem with a couple of programs now, and I can not figure out why this keeps happening. This is my code:
#include <stdio.h>
#include <math.h>
int main(void){
double x = 0;
while(x <= 0){
printf("Enter a digit greater than 0.\n");
scanf("%lf", &x);
}
printf("%lf", &x);
}
and the output is:
Enter a digit greater than 0.
4
0.000000
please help
Use the following code
#include <stdio.h>
#include <math.h>
int main(void){
double x = 0;
while(x <= 0){
printf("Enter a digit greater than 0.\n");
scanf("%lf", &x);
}
printf("%lf", x);
}
You are using
printf("%lf", &x);
But the correct syntax to print value of x is:
printf("%lf", x);
Check the working code https://ideone.com/lpdlmX
First off,
printf ("%lf", &x);
will try to print the address of x rather than its value, and this is clearly into undefined behaviour territory(a). A half-decent compiler should warn you about this such as, with gcc:
program.c: In function 'main':
program.c:13: warning: format '%lf' expects argument of type
'double', but argument 2 has type 'double *' [-Wformat=]
printf ("%lf\n", &x);
^
Secondly, the normal printf specifier for double is %f rather than %lf. You can use the latter since the standard states it has no effect on certain data types but it's a bit of a waste doing so.
So what you need is actually:
printf ("%f", x);
The general rule is that you pass addresses to scanf because it needs to populate the objects at those addresses. For printf, you just pass the object itself (yes, even if the data is a pointer that you want printed as a pointer rather than pointing the object being pointed to).
And, finally, to make your code more robust, you would be wise to detect a problem with scanf since, it there's a problem with the input that leaves x set to zero, the program will continuously try to read that input, resulting in an infinite loop.
So a good starting point, taking all those comments into consideration, would be:
#include <stdio.h>
#include <math.h>
int main (void) {
double x = 0;
while (x <= 0) {
printf ("Enter a digit greater than 0.\n");
if (scanf ("%lf", &x) != 1) {
printf ("Invalid input\n");
return 1;
}
}
printf ("%f\n", x);
return 0;
}
(a) Specifically, from ISO C11 7.21.6.1 /9:
If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
Always always check the return of scanf, that being said, you printf ("%f", x); -- there is no &x and no need for %lf, printf %f format specifiers prints doubles. (however it is required when using scanf -- man scanf and man printf are your friends)
Putting it altogether, you could safely take input as follows:
#include <stdio.h>
int main (void) {
double x = 0;
while(x <= 0){
printf ("Enter a digit greater than 0.\n");
if (scanf ("%lf", &x) != 1) {
fprintf (stderr, "error: invalid input.\n");
return 1;
}
}
printf ("%f", x);
}
note: you must exit the loop on conversion failure (or empty stdin before attempting to take input again -- or your input will fail) Reason: on a failed conversion - no additional characters are read leaving the characters causing the failure just waiting to bite you again on the next go-round...
I am doing school work and I came across a problem. Why do I loose the value of the variable n2?
#include <stdio.h>
#include <stdlib.h>
int opt;
double n1;
double n2;
int main()
{
printf("Hello and welcome \n");
printf("Lets do Some math! \n");
printf("Menu!\n");
printf("1- \t Areas \n");
printf("2- \t Perimetros \n");
scanf("%d",&opt);
switch (opt){
case 1:
Areas();
break;
case 2:
break;
}
return 0;
}
void Areas(){
printf("Area de:\n");
printf("1- \t Quadrado\n");
printf("2- \t Retangulo\n");
printf("3- \t Losangulo\n");
printf("1- \t Circulo\n");
scanf("%d", &opt);
switch (opt){
case 1:
Medidas("dos lados.");
printf("%d %d\n", n1,n2 );
break;
case 2:
break;
}
}
void Medidas(char string[]){
printf("Introduzir as Medidas %s \n", string);
scanf("%d", &n1);
printf("Next\n");
scanf("%d", &n2);
}
I tried many things and nothing works. The
printf("%d %d\n", n1,n2 );
is just for debugging purposes.
The problem is in
scanf("%d", &n1);
scanf("%d", &n2);
n1 and n2 are of type double, so using %d format specifier invokes undefined behavior.
Quoting C11, chapter §7.21.6.2, for fscanf(), (emphasis mine)
d Matches an optionally signed decimal integer, whose format is the same as
expected for the subject sequence of the strtol function with the value 10
for the base argument. The corresponding argument shall be a pointer to
signed integer.
and
[...] Unless assignment suppression was indicated by a *, the
result of the conversion is placed in the object pointed to by the first argument following
the format argument that has not already received a conversion result. If this object
does not have an appropriate type, or if the result of the conversion cannot be represented
in the object, the behavior is undefined.
solution: For printing doubles, you need to use %f and for scanning the values, you need to use %lf.
The variables n1 and n2 are of type double. However, you're using the %d format specifier in printf and scanf, which expect an int and a pointer to int.
For reading / writing a double, use the %f format specifier for printf and %lf for scanf.
You are using double data type for n1 and n2.
The printing format specifier for double is %f; the scanning format is %lf.
Instead of %d, use %f every time for n1 and n2.
To practice variable declaration, placeholders and I/O calls, I did a sample assignment in the book that I am using to study. However, I keep running into a particular problem, in that when I try to declare more than one character variable for the purpose of input, even if the compiler doesn't catch any syntax error, the program when executing will only return one character variable. This is the code in question:
#include <stdio.h>
int main()
{
double penny=0.01;
double nickel=0.05;
double dime=0.1;
double quarter=0.25;
double value_of_pennies;
double value_of_nickels;
double value_of_dimes;
double value_of_quarters;
double TOTAL;
int P;
int N;
int D;
int Q;
char a,b;
//used "static char" instead of "char", as only using the "char" type caused a formatting error where only the latter character entered in its input would appear
printf("Please enter initials> \n");
printf("First initial> \n");
scanf("%s", &a);
printf("Second initial> \n");
scanf("%s", &b);
//"%s" was used as the input placeholder for type "char"
printf("%c.%c., please enter the quantities of each type of the following coins.\n", a, b);
printf("Number of quarters> \n");
scanf("%d", &Q);
printf("Number of dimes> \n");
scanf("%d", &D);
printf("Number of nickels> \n");
scanf("%d", &N);
printf("Number of pennies> \n");
scanf("%d", &P);
printf("Okay, so you have: %d quarters, %d dimes, %d nickels, and %d pennies.\n", Q, D, N, P);
value_of_pennies=penny*P;
value_of_nickels=nickel*N;
value_of_dimes=dime*D;
value_of_quarters=quarter*Q;
TOTAL=value_of_quarters+value_of_dimes+value_of_nickels+value_of_pennies;
printf("The total value of the inserted coins is $%.2lf. Thank you.\n", TOTAL);
//total field width omitted as to not print out any leading spaces
return(0);
}
And this is the transcribed output ("a", "e", and the four "1"s are sample arbitrary input values:
Please enter initials>
First initial>
a
Second initial>
e
.e., please enter the quantities of each type of the following coins.
Number of quarters>
1
Number of dimes>
1
Number of nickels>
1
Number of pennies>
1
Okay, so you have: 1 quarters, 1 dimes, 1 nickels, and 1 pennies.
The total value of the inserted coins is $0.41. Thank you.
I entered the characters "a" and "e" as input values for the char variables "a" and "b", but only "e" had shown up. On the other hand, should I have put a "static" in the "char" variable declaration, both inputted char values will be displayed in the relevant print call.
For future reference, I would like to ask about why such a thing would occur the way that it did, and the value of the "static" word in the declaration.
(As an aside, I am aware that I could have simply made the "value_of_(insert coin here)" variables as constant macros.)
With a definition like
char a,b;
writing a statement like
scanf("%s", &a);
scanf("%s", &b);
invokes undefined behaviour. %s is not a format specifier for a char. Using wrong format specifier can and will lead to UB. You should use %c to scan a char.
To elaboreate,
%s format specifier expects a corresponding argument which is a pointer to char array. It scans multiple characters until it encounters a space (whitespace character, to be pedantic) or newline or EOF.
%c format specifier expects a corresponding argument which is a pointer to char variable. It reads only one char from the input buffer.
So, with %s, if you supply the adress of a char variable, it will try to access beyond the allocated memory region for writing the scanned data, which will invoke UB.
You may want to read some more on printf(), scanf() and format specifiers before moving forward.
You have used the wrong format specifier for char. char uses %c not %s. As far as static goes, I'm a bit confused about your question. You say in a comment that you are using static char, but I do not see any variables declared as static char.