Today, I faced some weird issue with ARM toolchain EABI (cross-compiler).
Ths issue is when i try to use snwprintf() for converting floating point value to string , i was getting some junk string which does not have actual floating point value that i passed.
smaple code looke like this:
float floatValue = 1.0;
snwprintf (buffer, bufferSize, _T("%g"), floatValue);
I then debugged snwprintf and i found out that variable argument list (va_arg) is not pointing to exact data value. And by dumping the memory we were able to find the exact data present in the variable argument list. The data that should be pointed by va_arg is differing.
I don't think this is an endianess issue as integre value is working fine. The problem is only with double values.
Can anyone help me in this issue?
You should format/print it as a double, since floats are widened to doubles for variadic functions.
Procedure Call Standard for the ARM Architecture states following
5.5 Parameter Passing
A variadic function is always marshaled as for the base standard.
7.2 Argument Passing Conventions
For variadic functions, float arguments that match the ellipsis (…) are converted to type double.
Afaik 7.2 holds for C in general.
Related
What is the point of format specifier in C if we have allready set the type of variable before printf?
For example:
#include<stdio.h>
int main(void)
{
int a=7
printf("%d", a);
}
Like, it's allready stated what a is, it's integer(int). So what is the point of adding %d to specify that it's an integer?
The answer to this question really only makes sense in the context of C's history.
C is, by now, a pretty old language. Though undoubtedly a "high level language", it is famously low-level as high-level languages go. And its earliest compiler was deliberately and self-consciously small and simple.
In its first incarnation, C did not enforce type safety during function calls. For example, if you called sqrt(144), you got the wrong answer, because sqrt expects an argument of type double, but 144 is an int. It was the programmer's responsibility to call a function with arguments of the correct types: the compiler did not know (did not even attempt to keep track of) the arguments expected by each function, so it did not and could not perform automatic conversions. (A separate program, lint, could check that functions were called with the correct arguments.)
C++ corrected this deficiency, by introducing the function prototype. These were inherited by C in the first ANSI C standard in 1989. However, a function prototype only works for a function that expects a single, fixed argument list, meaning that it can't help for functions that accept a variable number of arguments, the premier example being: printf.
The other thing to remember is that, in C, printf is a more or less ordinary function. ("Ordinary" other than accepting a variable number of arguments, that is.) So the compiler has no direct mechanism to notice the types of the arguments and make that list of types available to printf. printf has no way of knowing, at run time, what types were passed during any given call; it can only rely (it must rely) on the clues provided in the format string. (This is by contrast to languages, many of them, where the print statement is an explicit part of the language parsed by the compiler, meaning that the compiler can do whatever it needs to do in order to treat each argument properly according to its known type.)
So, by the rules of the language (which are constrained by backwards compatibility and the history of the language), the compiler can't do anything special with the arguments in a printf call, other than performing what is called the default argument promotions. So the compiler can't fix things (can't perform the "correct" implicit conversion) if you write something like
int a = 7;
printf("%f", a);
This is, admittedly, an uncomfortable situation. These days, programmers are used to the protections and the implicit promotions provided for by function prototypes. If, these days, you can call
int x = sqrt(144);
and have the right thing happen, why can't you similarly call
printf("%f\n", 144);
Well, you can't, although a good, modern compiler will try to help you out anyway. Although the compiler doesn't have to inspect the format string (because that's printf's job to do, at run time), and the compiler isn't allowed to insert any implicit conversions (other than the default promotions, which don't help here), a compiler can duplicate printf's logic, inspect the format string, and issue strong warnings if the programmer makes a mistake. For example, given
printf("%f\n", 144);
gcc prints "warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘int", and clang prints "warning: format specifies type 'double' but the argument has type 'int'".
In my opinion, this is a fine compromise, balancing C's legacy behavior with modern expectations.
what is the point of adding %d to specify that it's an integer?
printf() is a function which receives a variable number of arguments of various type after the format argument. It does not directly know the number nor the type of arguments passed nor received.
The callers knows the argument count and types it gives to printf().
To pass the arguments count and type information, the format argument is used by the caller to encodes the argument count and types. printf() uses that format and decodes it to know the argument count and type. It is very important that the format and following arguments passed are consistent.
printf() accepts a variable number of arguments. To process those variable arguments it (va_start()) needs to know the last fixed argument is. It (va_arg()) also needs to know the type of each argument so it figure how much data to read.
The format specifier is also a compact template (or DSL) to express how text and variables should be formatted including field width, alignment, precision, encoding.
We recently took an exam were we got this question:
Consider this fragment of code:
FILE * pFile;
pFile = open ("myfile.txt","w+");
fprintf (pFile, "%f %s", 3.1416, "PI");
Which of the following statements are true?
A)The program generates error at compile time
B)The program generates error at runtime
C) . . .
D) . . .
We couldn't use the compiler, and the information wrote is the only thing we had.
The correct answer ended up being B, error at runtime, can someone explain me thoroughly why that is?
I know the compiler generates a warning, but the point here is to understand why the compiler let us compile this code in the first place instead of giving us an error.
My guess is that open, even though doesn't give a pointer back(which is an address), gives the fp which is still an int, so in the eyes of the compiler isn't wrong syntax, but at runtime it probably tries to access a private memory address which leads to an error.
p.s.
I know that the correct function should have been fopen, but that still doesn't explain why
This code has two specific issues:
The second parameter to open expects an int but a char * is passed instead
open returns an int but that value is assigned to a FILE *.
The compiler flags these as warnings instead of errors because the language allows a pointer to be converted to an integer, and for an integer to be converted to a pointer. However, doing so is generally implementation defined and usually (as in this case) but not always indicates a problem.
Section 6.3.2.3 of the C standard describes these conversions:
5 An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined,
might not be correctly aligned, might not point to an entity
of the referenced type, and might be a trap representation.
6 Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the
result cannot be represented in the integer type,the behavior
is undefined. The result need not be in the range of values
of any integer type.
Going over some code (written in the C language) I have stumbled upon the following:
//we have a parameter
uint8_t num_8 = 4;
//we have a function
void doSomething(uint32_t num_32) {....}
//we call the function and passing the parameter
doSomething(num_8);
I have trouble understanding if this a correct function calling or not. Is this a casting or just a bug?
In general, I know that in the C / C++ languages only a copy of the variable is passed into the function, however, I am not sure what is actually happening. Does the compiler allocates 32 bits on the stack (for the passed parameter), zeros all the bits and just after copies the parameter?
Could anyone point me to the resource explaining the mechanics behind the passing of parameter?
As the function declaration includes a parameter type list, the compiler knows the type of the expected parameter. It can then implicitely cast the actual parameter to the expected type. In fact the compiler processes the function call as if it was:
doSomething((uint32_t) num_8);
Old progammers that once used the (not so) good K&R C can remember that pre-ansi C only had identifier lists and the type of parameters was not explicitely declared. In those day, we had to explicitely cast the parameters, and when we forgot, we had no compile time warnings but errors at execution time.
The way the cast and the call is precisely translated in assembly language or machine instruction is just an implementation detail. What matters is that everything must happen as if the compiler had declared a temporary uint32_t variable had coerced the uint8_t value into the temporary and had passed the temporary to the function. But optimizing compilers often use a register to pass a single integer parameter. Depending on the processor, it could zero the accumulator, load the single byte in the low bits and call the function.
I am new to programming. I was finding a square root of a number using sqrt()function in c. `
scanf("%d", &n);
printf("%d\n", sqrt(n));
}
return 0;
}
When I enter a value of n = 5, I got some negative large number. Can anyone explain, please?
You've produced undefined behavior by passing the wrong type to printf: the %d format required a matching argument of type int but your argument has type double. You need %f (or %e or %g or %a) to print it. Also, there may be other problems, e.g. if you omitted #include <math.h>.
As others have pointed out, the problem here is that the format specifier is wrong. You need to #include <math.h> to get the proper return type of sqrt(), then use a format specifier like %f. Also, turn up your compiler warnings until it tells you something was wrong here. -Wall -Wextra -pedantic -Wno-system-headers is a good choice.
I’m adding an answer, though, to provide historical background on why float variables get promoted to double in printf() argument lists, but not scanf(), since this confused people in the comments.
In the instruction set of the DEC PDP-10 and PDP-11 computers, on which C was originally developed, the float type existed only to save space, and a program needed to convert a float to double to do any calculations on it. In early versions of C, before ANSI function prototypes, all float arguments to a function were promoted to double automatically before being passed (and also char to int). Originally, this ran better at a low level, and also had the advantage of avoiding round-off and overflow error on math using the shorter types. This convention also simplified writing functions that took a varying number of arguments of varying types, such as printf(). The caller could just pass anything in, the compiler would let it, and it was the called function’s job to figure out what the argument list was supposed to be at runtime.
When C added function prototypes, these old rules were kept for backward-compatibility only with legacy function declarations (extern double sqrt() rather than extern double sqrt(double) or the C14 generic equivalent). Since basically nobody writes functions that way any more, this is a historic curiosity—with one exception. A varargs function like int printf(const char*, ...); cannot be written in C with type checking of the variable arguments. (There is a C++14 way to do this using templates.) The standards committee also did not want to break all existing code that printed a float. So those are still promoted according to the old rules.
In scanf(), none of this applies because the storage arguments are passed by reference, and scanf() needs to be sure it’s writing the data in the same type as the variable that holds it. Argument-promotion never comes into play, because only pointers are ever passed.
I meet the same problem. And I want to get an answer with int type. I use forced type conversion, like:
printf("%d\n", (int)sqrt(n));
this is happens because return type and input type of the sqrt() is not specified ,
you can solve this by either including the header file by :
#include<math.h>
or by explicitly specifying the return and input type like this :
double sqrt(double);
and also as mentioned above use correct format specifiers (eg : %f) .
what shall be the output of: (and why?)
printf("%d",2.37);
Apparently, printf is a variadic function and we can never know the type of a variable argument list. so we always have to specify the format specifiers manually.
so, 2.37 would be stored as double according to IEEE standards would be fetched and printed in integer format.
But the output is 0.
What is the reason?
It is undefined behavior. You're passing a double argument to a function that expects to retrieve an int from its varargs macros, and there's no telling at all what that is going to lead to. In theory, it may even crash (with a calling convention that specifies that variadic arguments of different types are passed in different ways or on different stacks).