Multiple Inputs in one scanf showing a miscellanous behaviour - c

I was trying a simple calculation using long data types. Addition of three numbers. But while I take inputs in one scanf function, it take takes intial two input as zero.
#include <stdio.h>
int main()
{
long x,y,z;
printf("Input x,y,x:\n");
scanf("%lld %lld %lld",&x,&y,&z);
printf("Result: %lld\n",x+y+z);
return 0;
}
The code works perfectly fine in online compiler but not in my vscode. I checked the version of C we are using the same.
I changed the code a little, i.e.,
scanf("%lld %lld %lld",&z,&y,&x);
and now it works perfectly fine.
Why? How can just the arrangement of variable solved the issue.
I did the initial code in int data type with %d format specifier, it worked perfectly fine but not the same with long and %lld.
Can anyone explain why this happened or what is the error.
Why does it works on online compiler but not my vs code.
I was expecting the sum of three numbers.

The %lld specifier expect the address of a long long. You instead passed in the address of a long. Using the wrong format specifier triggers undefined behavior.
What most likely happened, given that you're using VS Code and therefore most likely running on Windows, on that system a long is 4 bytes while a long long is 8 bytes. So when scanf attempts to read a value, it writes 8 bytes into the the pointer it's given instead of 4, writing past the end of a variable and most likely into another.
The online compiler you're using is probably using gcc which has an 8 byte long so it happens to work.
You should instead be using the %ld format specifier which expects the address of a long.
scanf("%ld %ld %ld",&x,&y,&z);

It's happening because you have used the wrong format specifier of long. Either declare the variables as long and use the format specifier as %ld or declare the variables as long long and use the format specifier as %lld

Related

DataTypes and format specifier

Why the value of the input variable is set to zero if I pass incorrectly ordered type specifier for id variable?
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#define MAX 100
int main()
{
int i=0;
int input;
char *name=(char *)malloc(sizeof(char)*MAX);
unsigned short int id;
printf("\nPlease enter input:\t");
scanf("%d", &input);
getchar();//to take \n
printf("\nEnter name.....\n");
fgets(name,MAX,stdin);
printf("\nEnter id: ");
scanf("%uh",&id);//type specifier should have been %hu
printf("%d",input);//value set to 0?
}
Why is input being overridden by scanf("%uh", &id) ?
Jyoti Rawat
You have what I call a memory over run error. Microsoft (Visual Studio) calls it:
"Stack around the variable ‘id’ was corrupted"
Not all computer systems treat memory over runs errors the same. Visual Studio/Windows catch this error and throw an exception.
OpenVMS would just execute the instruction and then continue on to the next instruction. In either case, if the program continues, its behavior will be undefined.
In English, you are writing more bits of data into a variable that cannot contain it. The extra bits are written to other memory locations not assigned to the variable. As mention by chux, statements that follow will have undefined behavior.
Solution:
As you already know and mention by others, change the format specifier from "uh" to "hu".
Things to note about your code:
As stated my Adrian, using "hu" as a format specifier will work.
This specifier expects a pointer to a unsigned short int variable. Click here to go to scanf format specifiers wiki page.
When you specify “%uh”, scanf pares out the %u as the format
specifier and treats the rest ('h') as text to be ignored.
The format specifier 'u' expects a pointer to an unsigned int variable (unsigned int *).
The format specifier 'hu' expects a pointer to an unsigned short variable (unsigned short
int *).
Why the value of the input variable is set to zero if I pass incorrectly ordered type specifier to id variable?
unsigned short int id;
scanf("%uh",&id);//type specifier should have been %hu
scanf() first uses "%u" and looks for a matching unsigned * argument. As code passed a unsigned short * the result is undefined behavior (UB).
The result of 0 is not demo'd with printf("%d",input);. Perhaps OP meant printf("%d",id);?
In any case, code after the UB of scanf() is irrelevant. It might print 0 today or crash the code tomorrow - it is UB.
EDIT (After re-reading question/comments):
Mentat has nailed the problem! I'll leave some fragments of my original answer, with some additions ...
(1) The warning about using %uh should be accepted at face value: to input a short integer (signed or unsigned), you need the h modifier before the type specifier (u or d) - that's just the way scanf format specifiers work.
(2) Your code happens to work on MSVC, so I missed the point. With clang-cl I found your error: As the h size modifier is being ignored, the value read in by '%uh' is a (long or 32-bit) unsigned, which is being written to memory that you've allocated as a short (16-bit) unsigned. As it happens, that variable (id)is in memory next to input, so part of input is being overwritten by the high 16-bits of the 32-bit unsigned you are writing to id.
(3) Try entering a value of 65537 for your first input and then the value will still be modified (probably to 65536), but not cleared to zero.
(4) Recommend: Accept and upvote the answer from Mentat. Feel free to downvote my answer!
Yours, humbly!

C printf of an integer with %lu produces large number

I know that is bad practice to print an integer with %lu which is a unsigned long. In a project i was working on i got a large number when trying to print 11 with %lu in the snprint format.(old code) I am using gcc 4.9.3.
This code below i thought would produce the wrong number since snprintf is told to read more than the 4 bytes occupied. Its doesnt though. Works perfectly. It reads everything correctly. Either it does not go past the 4 bytes in to the unknown or the extra 4 bytes in the long are fully of zeros when it gets promoted to long from int.
I am wondering out of curiosity is when does printf print the wrong number? What conditions does it need produce a wrong big number? There has to be garbage in the upper 4 bytes but it seems like it does not set that garbage for me.
I read the answers here but the code worked for me. I know its a different compiler.
Printing int type with %lu - C+XINU
#include<inttypes.h>
#include<stdio.h>
int main(void){
uint32_t number1 = 11;
char sentence[40];
snprintf(sentence,40,"Small number :%lu , Big number:%lu \n",number1,285212672);
printf(sentence);
}
On OP's machine, uint32_t, unsigned long and int appear to be the same size #R Sahu. OP's code is not portable and may produce incorrect output on another machine.
when does printf print the wrong number?
Use the matching printf() specifier for truly portable code. Using mis-matched specifiers may print the wrong number.
The output string may be well over 40 characters. Better to use a generous or right-sized buffer.
#include <inttypes.h>
#include <stdio.h>
int main(void){
uint32_t number1 = 11;
// char sentence[40];
char sentence[80];
snprintf(sentence, sizeof sentence,
"Small number :%" PRIu32 " , Big number:%d \n",
number1, 285212672);
// printf(sentence); // Best not to print a string using the printf() format parameter
fputs(sentence, stdout);
}

C int datatype and its variations

Greetings , and again today when i was experimenting on language C in C99 standard , i came across a problem which i cannot comprehend and need expert's help.
The Code:
#include <stdio.h>
int main(void)
{
int Fnum = 256; /* The First number to be printed out */
printf("The number %d in long long specifier is %lld\n" , Fnum , Fnum);
return 0;
}
The Question:
1.)This code prompted me an warning message when i try to run this code.
2.)But the strange thing is , when I try to change the specifier %lld to %hd or %ld,
the warning message were not shown during execution and the value printed out on the console is the correct digit 256 , everything also seems to be normal even if i try with
%u , %hu and also %lu.In short the warning message and the wrong printing of digit only happen when I use the variation of long long specifier.
3.)Why is this happening??I thought the memory size for long long is large enough to hold the value 256 , but why it cannot be used to print out the appropriate value??
The Warning Message :(For the above source code)
C:\Users\Sam\Documents\Pelles C Projects\Test1\Test.c(7): warning #2234: Argument 3 to 'printf' does not match the format string; expected 'long long int' but found 'int'.
Thanks for spending time reading my question.God bless.
You're passing the Fnum variable to printf, which is typed int, but it's expecting long long. This has very little to do with whether a long long can hold 256, just that the variable you chose is typed int.
If you just want to print 256, you can get a constant that's typed to unsigned long long as follows:
printf("The number %d in long long specifier is %lld\n" ,256 , 256ULL);
or cast:
printf("The number %d in long long specifier is %lld\n" , Fnum , (long long int)Fnum);
There are three things going on here.
printf takes a variable number of arguments. That means the compiler doesn't know what type the arguments (beyond the format string) are supposed to be. So it can't convert them to an appropriate type.
For historical reasons, however, integer types smaller than int are "promoted" to int when passed in a variable argument list.
You appear to be using Windows. On Windows, int and long are the same size, even when pointers are 64 bits wide (this is a willful violation of C89 on Microsoft's part - they actually forced the standard to be changed in C99 to make it "okay").
The upshot of all this is: The compiler is not allowed to convert your int to a long long just because you used %lld in the argument list. (It is allowed to warn you that you forgot the cast, because warnings are outside standard behavior.) With %lld, therefore, your program doesn't work. But if you use any other size specifier, printf winds up looking for an argument the same size as int and it works.
When dealing with a variadic function, the caller and callee need some way of agreeing the types of the variable arguments. In the case of printf, this is done via the format string. GCC is clever enough to read the format string itself and work out whether printf will interpret the arguments in the same way as they have been actually provided.
You can get away with slightly different types of arguments in some cases. For example, if you pass a short then it gets implicitly converted to an int. And when sizeof(int) == sizeof(long int) then there is also no distinction. But sizeof(int) != sizeof(long long int) so the parameter fails to match the format string in that case.
This is due to the way varargs work in C. Unlike a normal function, printf() can take any number of arguments. It is up to the programmer to tell printf() what to expect by providing a correct format string.
Internally, printf() uses the format specifiers to access the raw memory that corresponds to the input arguments. If you specify %lld, it will try to access a 64-bit chunk of memory (on Windows) and interpret what it finds as a long long int. However, you've only provided a 32-bit argument, so the result would be undefined (it will combine your 32-bit int with whatever random garbage happens to appear next on the stack).

greater integer width

i m trying to enter a five digit number greater than 32767 and i used "unsigned" while declaring int number, and when i m trying to print the same number it prints some arbitary negative number,
results get overflowed......
pls help me out
Without seeing your code, I am guessing you are using %d or %i in the printf statement. Use %u instead.
Print unsigned values using "%u" instead of "%d".
Until you show some of the code, I can't be sure of anything.
But AFAIK you shouldn't be able to print out a negative number if you're printing out an uint – even if it overflows, the integer will always hold a positive number, as far as C is concerned.
So there's something else wrong.
Use correct format specifier.
%d for int
%u for unsigned int.
Using incorrect format specifier in printf() may cause Undefined Behavior.
For example, the following code invokes Undefined Behavior(UB).
#include<stdio.h>
int main(void)
{
unsigned int z=Some_value; /*Some_value is an unsigned int */
printf("%d",z);
/*UB as format specifier for unsigned int is incorrect,it should be %u not %d*/
}
I guess int is 16bit on your machine/compiler.
Though I don't know what your platform is, I guess that long would solve your problem (it is 32bit or more on all platforms I know). Print it with %ld instead of %d.
Don't get tempted to use unsigned and %u, because they will just give you numbers up to 65536, and I guess that you want more.

Integer Overflow

I have an unsigned long long that I use to track volume. The volume is incremented by another unsigned long long. Every 5 seconds I print this value out and when the value reaches the 32 bit unsigned maximum the printf gives me a negative value. The code snippet follows:
unsigned long long vol, vold;
char voltemp[10];
vold = 0;
Later...
while (TRUE) {
vol = atoi(voltemp);
vold += vol;
fprintf(fd2, "volume = %llu);
}
What am I doing wrong? This runs under RedHat 4 2.6.9-78.0.5.ELsmp gcc version 3.4.5
Since you say it prints a negative value, there must be something else wrong, apart from your use of atoi instead of strtoull. A %llu format specifier just doesn't print a negative value.
It strongly looks like the problem is the fprintf call. Check that you included stdio.h and that the argument list is indeed what is in the source code.
Well I can't really tell because your code has syntax errors, but here is a guess:
vol = atoi(voltemp);
atoi converts ascii to integer. You might want to try atol but that only gets it to a long, not a long long.
Your C standard library MIGHT have atoll.
You can't use atoi if the number can exceed the bounds of signed int.
EDIT: atoll (which is apparently standard), as suggested, is another good option. Just keep in mind that limits you to signed long long. Actually, the simplest option is strtoull, which is also standard.
Are you sure fprintf can take in a longlong as a parameter, rather than a pointer to it? It looks like it is converting your longlong to an int before passing it in.
I'd guess the problem is that printf is not handling %llu the way you think it is.
It's probably taking only 32 bits off the stack, not 64.
%llu is only standard since C99. maybe your compiler likes %LU better?
For clarification the fprintf statement was copied incorrectly (my mistake, sorry). The fprintf statement should actually read:
fprintf(fd2, "volume = %llu\n", vold);
Also, while admittedly sloppy the maximum length of the the array voltemp is 9 bytes (digits) which is well within the limits of a 32-bit integer.
When I pull this code out of the program it is part of and run it in a test program I get the result I would expect which is puzzling.
If voltemp is ever really big, you'll need to use strtoull, not atoi.

Resources