a strange thing when test unsigned int value - c

today,I write some code to test unsigned int.
#include <stdio.h>
int sum_element(float ele[], unsigned int len);
int main(void){
float ele[] = {1.1,2.2,3.3};
float sum = sum_element(ele,3);
printf("sum is %f\n",sum);
return 0;
}
int sum_element(float ele[], unsigned int len){
int sum=0.0; //mistake,should be : float sum = 0.0
int i=0;
for(i=0;i<= len-1;i++){
printf("sum=%f, i=%d\n",sum,i);
sum += ele[i];
}
return sum;
}
in this example, i have a mistake, the type of variable sum, should be float, but i write int, the compile command:
gcc test.c -o test
and i run this code
./test
the output of the function sum_element is:
sum=0.000000, i=1
sum=0.000000, i=1
sum=0.000000, i=1
and then i found the mistakes, and i change the type of sum to float, then compiled again,
and when i run it, the output is :
sum=0.000000, i=0
sum=1.100000, i=1
sum=3.300000, i=2
this time, the output like normal,but in first output, why the variable of i is always the same value of 1, can someone tell me?

Nothing to see. You invoked undefined behavior by passing the wrong type to printf, so all output of the program is meaningless. The %f format specifier requires an argument of type double (by the way, float would automatically promote to double in this context, so float would be okay too), but you passed it an argument of type int.

You have to understand how va_arg work. Printf is a function that take a undefined number of arguments. The problem is that those arguments are not typed.
When you specify int, double, ect... the compiler assign differente number of bytes (in a specific order) depending on the arguments. So when you call a function that has type argument, the function know how it should read those bytes.
Here it cannot know since it isn't type. So the printf function is going to believe what you give it. If you ask for example for a 4 bytes when you real value is 8 bytes, the function will read the first 4 bytes believing it the value you ask for. But then the next value you try to match will start with the next 4 bytes. Wich will give you garbage.
You can try to do 2 printf, and you will see that the value of i is actually the good one. Only the way to read it was wrong.
int sum_element(float ele[], unsigned int len){
int sum=0.0; //mistake,should be : float sum = 0.0
int i=0;
for(i=0;i<= len-1;i++){
printf("sum=%f\n",sum);
printf("i=%d\n",i);
}
return sum;
}
Hope this can help.
EDIT:
Maybe a example is easier to understand. Try this function:
int sum_element(float ele[], unsigned int len){
int sum=24222.55455555; //mistake,should be : float sum = 0.0
char c = 0 ;
for(i=0;i<= len-1;i++){
printf("sum=%f, n= %d n2 = %d\n",sum,i,c);
}
return sum;
}
You should get a interesting value for n2.

I think the answer is that in the first case, the value being printed is not that of i at all. Two parameters are passed to printf which then reads two off. Those passed in are two ints, and then a double and and int are read off. Because the double is read off the stack first, when the int is read it is not from where the value of i was passed, hence the bogus value. Most likely the double covers enough of the stack to include both the passed ints.
Of course, results may vary, being undefined.

Related

My function will give correct answers on only one call but not on multiple

I'm making a code for converting Decimal numbers to Binary(university assignment). If I only do DecToBinary(5) it gives me 101, and if I only do DecToBinary(6) it gives me 110, but when i do both of these statements in main() it gives me 101110101 when it should just give me 101110(joining the two answers above). I don't understand what is going on since it should just call DecToBinary(5) and print 101 then (without adding a newline character) call DecToBinary(6) and print 110.
void DecToBinary(int dec){
int temp[64]; //64 is just a max value
int i,j;
while(dec>0){
temp[i]=dec%2;
dec=dec/2;
i++;
}
for(j=0;j<i;j++){
printf("%d",temp[i-1-j]);
}
}
You haven't initialized the variable i. This means that the behaviour of your program is undefined, as the value of i may be different of 0 which is what you want.
To correct it, you just have to initialize i when declaring it, meaning int i = 0
The variable i is not initialized
int i,j;
so the function has undefined behavior.
You need to initialize it before the while loop.
Also the while loop should be substituted for a do-while loop. Otherwise the value 0 will not be processed correctly. For example
i = 0;
do
{
temp[i++] = dec % 2;
} while( dec /= 2 );
Also as the function does not process negative numbers then its parameter should have the type unsigned int
void DecToBinary( unsigned int dec )
Always initliaze variable. Check i and j in your case.

To generate an integer output for a float variable in c

Okay this is actually a very simple code but since I am only starting to learn C, please be patient and help me out. I'll be putting my Questions as comments beside the code so that it easy to relate to which part of the code I have a doubt.
#include <stdio.h>
main()
{
int first_no, second_no;
float dec_no, output_no;
first_no = 75;
second_no = first_no/2;
dec_no = 35.3;
output_no = dec_no/3;
printf("First No:%d\n", first_no);
printf("Second No:%d\n", second_no);
printf("Third No:%d\n",output_no);
/*here I wanted to print only the integer part of the output_no */
}
The problem with this is that I had a book and it displayed the value for third no as 0.
And then in another program it says that compile time error is shown.
Second program:
#include <stdio.h>
void main()
{
int x = 5.3%2;
printf("Value of x is %d", x);
}
For this program, the book says that a compile time error will be shown. I fail to understand why that is the case. According to me the output should be 1.
If I were to use the following code instead of the previous code:
#include <stdio.h>
main()
{
int first_no, second_no;
float dec_no, output_no;
first_no = 75;
second_no = first_no/2;
dec_no = 35.3;
output_no = dec_no/3;
printf("First No:%d\n", first_no);
printf("Second No:%d\n", second_no);
printf("Third No:%d\n",dec_no);
}
What output should I expect? Do I still get a zero or some unpredictable output?
The problems with using just
printf("Third No:%d\n",output_no);
is that:
output_no gets converted to a double before being passed to printf.
When printf sees %d as the format specifier, it expects an int. When the object being passed is of type double, the behavior is undefined.
When you want to print a truncated integral value of a floating point number, you can do one of the following.
Create a temporary variable of the integral type and assign to it the floating point number.
int temp = output_no;
printf("Third No:%d\n", temp);
Explicitly cast the floating point number to an integral type.
printf("Third No:%d\n", (int)output_no);
printf("Third No:%d\n",dec_no);
What output should I expect? Do I
still get a zero or some unpredictable output?
As of the printf function is concerned,
When you try to print an integer value with format specifiers that are used for float (or) double and vice the versa the behaviour is unpredictable.
But it is possible to use %c to print the character equivalent of the integer value. Also using of %d to print ASCII value (integer representations) of character is acceptable.
Second program: For this program, the book says that a compile time
error will be shown.
According to C Reference manual
7.3.3 expression % expression
The binary % operator yields the remainder from the division of the first expression by the second. Both operands must be int or char, and
the result is int. In the current implementation, the remainder has
the same sign as the dividend.
Here in your case you are providing one value 5.3 so it is neither char nor int so that is why it generates compilation error.
If you still want to run that program you can do that by using fmod() function.
Try this code :
#include<stdio.h>
#include<math.h>
void main()
{
float x=5.3;
int c =2;
printf("Value of xremainer is %lf",fmod(x,c));
}
Compile it as :
$gcc test.c -lm

why is this pass by pointer is not working as intended?

I am trying to understand why the following code does not work... please help:
void incme(double *p)
{
printf("%x,%x\n",p,*p);
*p = *p + 1;
printf("%x,%x\n",p,*p);
}
int main()
{
int i = 1;
incme((double *)&i);
printf("%x,%x",&i,i);
}
the output is:
ff99a348,1
ff99a348,1
ff99a348,1
I am expecting:
ff99a348,1
ff99a348,2
ff99a348,2
it breaks everything I know about pointers...
Thanks.
EDIT:
the main question i am asking the the type cast in incme((double *)&i); why isit not casting it to double and pass it to the function ? ... sorry for not pointing out eailer ....
Because of undefined behavior. Integers are not floating point, and floating point is not integers. Besides that, I think you will find that sizeof(int) != sizeof(double).
You're also breaking the strict aliasing rule.
Unrelated to your question, you should use the "%p" format if you want to print pointers.
When you do *p = *p + 1; with p beeing a double* there is a lot going under the hood, indeed, double are represented using a custom format (wiki), when you use printf to display it as a integer after that, the internal representation of the memory at this address has changed (to a double representation), this is why you obtain such a result.
I ran the code and obtained the following output:
205afc2c,205afd28
205afc2c,593b4ab0
205afc2c,0
It shows use that the value is invalid as a double, and when it's incremented, it does not update the sizeof(int) first bits of the double (as it print 0 in the last line).
Hope I made myself clear !
Edit
I changed the code a little to show you what actually happen:
void incme(double *p)
{
printf("%x,%lf\n",p,*p);
*p = *p + 1;
printf("%x,%lf\n",p,*p);
}
int main()
{
int i = 1;
incme((double *)&i);
printf("%x, %lf, %d",&i,i, i);
}
Gives me the following output:
cb90990c,0.000000
cb90990c,1.000000
cb90990c, 1.000000, 0
As you can see, if you print them as double, the value is indeed correct (but the binary representation of 1.0000 is not 00000000001 as I said previously, this is why the hex formatting gives you a large number).
Back in the main, if you display the value as a double (event if i is supposed to be a int) as the incme function changed the memory layout of it, it does print 1.0000, but the first 32bits of the memory at this address are 0 hence, printing it as an int gives you 0.
The main reason, the printf statements should read -
printf( "%p,%f", p, *p );
This will show your increment of the double.
Also - as stated, an int is generally 4 bytes and a double uses 8 bytes. (on most systems)

Please help me to understand these error

#include<stdio.h>
float func (float t, float y){
return y ;
}
int main (){
float t0,y0,t,y;
printf ("the value of t: ");
scanf ("%f",&t0);
printf ("the value of y: ");
scanf ("%f",&y0);
t=t0;
y=y0;
static int n=0;
// t[0]=t0;
// y[0]=y0;
for (n=0;n<=3;n++){
y[1]=y[0];
printf ("value of y %f %f \n",t,y);
}
return 0;
}
The error is:
Building prog.obj.
D:\master\c language\ch3\prog.c(166): warning #2117: Old-style function definition for 'main'.
D:\master\c language\ch3\prog.c(182): error #2144: Type error: pointer expected.
D:\master\c language\ch3\prog.c(182): error #2144: Type error: pointer expected.
*** Error code: 1 ***
You cannot array index something that is not an array, or a pointer into an array.
Your y and t floats are not pointers into arrays in your program.
You should make them float *y, *t into pointers so you can point them into array.
Change float t0,y0,t,y; to float t0,y0,*t,*y;
and
t=&t0; //assign address of t0 to t
y=&y0;
Change printf ("value of y %f %f \n",t,y); to
printf ("value of y %f %f \n",*t,*y); //note to dereference t and y here, to get their values
Here's a example of your program I fixed to work
The 'Old-style function definition for main()' message means that you've not given a prototype definition. The correct forms are:
int main(void) { ... }
int main(int argc, char **argv) { ... }
The version int main() is fine in C++, but not strictly a prototype in C, and hence gets the 'old-style' tag.
The other messages are more inscrutable; the line numbers do not correspond to the code you show. However, as Tony The Lion notes in his answer, the line
y[1] = y[0];
is erroneous since y is not an array. There is room to think that should be:
y = y0;
and you'd need a companion:
t = t0;
in order to have defined values printed in the printf() statement.
Even with these changes, the code does not make a lot of sense. However, given that you removed 150-odd lines, we can suppose that the missing code would make more sense.
There is no need to make n into a static variable; it is better not to do so.
Please make sure, in future, that your error messages correspond to the source code you post, not to some variant version of the code you post. The line numbers should not be as large as 166 or 182; they should be single digit numbers or small double digit numbers. But even more importantly, they should match the code!

How to printf long long

I'm doing a program that aproximate PI and i'm trying to use long long, but it isn't working.
Here is the code
#include<stdio.h>
#include<math.h>
typedef long long num;
main(){
num pi;
pi=0;
num e, n;
scanf("%d", &n);
for(e=0; 1;e++){
pi += ((pow((-1.0),e))/(2.0*e+1.0));
if(e%n==0)
printf("%15lld -> %1.16lld\n",e, 4*pi);
//printf("%lld\n",4*pi);
}
}
%lld is the standard C99 way, but that doesn't work on the compiler that I'm using (mingw32-gcc v4.6.0). The way to do it on this compiler is: %I64d
So try this:
if(e%n==0)printf("%15I64d -> %1.16I64d\n",e, 4*pi);
and
scanf("%I64d", &n);
The only way I know of for doing this in a completely portable way is to use the defines in <inttypes.h>.
In your case, it would look like this:
scanf("%"SCNd64"", &n);
//...
if(e%n==0)printf("%15"PRId64" -> %1.16"PRId64"\n",e, 4*pi);
It really is very ugly... but at least it is portable.
Your scanf() statement needs to use %lld too.
Your loop does not have a terminating condition.
There are far too many parentheses and far too few spaces in the expression
pi += pow(-1.0, e) / (2.0*e + 1.0);
You add one on the first iteration of the loop, and thereafter zero to the value of 'pi'; this does not change the value much.
You should use an explicit return type of int for main().
On the whole, it is best to specify int main(void) when it ignores its arguments, though that is less of a categorical statement than the rest.
I dislike the explicit licence granted in C99 to omit the return from the end of main() and don't use it myself; I write return 0; to be explicit.
I think the whole algorithm is dubious when written using long long; the data type probably should be more like long double (with %Lf for the scanf() format, and maybe %19.16Lf for the printf() formats.
First of all, %d is for a int
So %1.16lld makes no sense, because %d is an integer
That typedef you do, is also unnecessary, use the type straight ahead, makes a much more readable code.
What you want to use is the type double, for calculating pi
and then using %f or %1.16f.
// acos(0.0) will return value of pi/2, inverse of cos(0) is pi/2
double pi = 2 * acos(0.0);
int n; // upto 6 digit
scanf("%d",&n); //precision with which you want the value of pi
printf("%.*lf\n",n,pi); // * will get replaced by n which is the required precision

Resources