sprintf leaves out double data C [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 11 months ago.
The community reviewed whether to reopen this question 11 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
The sprintf function is not including the variables which I have included.
I have the following code:
typedef struct
{
double sensor_1;
double sensor_2;
double sensor_3;
double sensor_4;
int32_t acc_count;
}PAC1934_ResultData_t;
here is the struct for the power sensor.
PAC1934_ResultData_t power;
power = PAC1934_read_Power_accumulation();
uint8_t buf[100] = {0};
sprintf((char*)&buf, " %010.9f W %010.9f W %010.9f W %010.9f W \n\r",
power.sensor_1, power.sensor_2, power.sensor_3, power.sensor_4);
But the value of buf is always just some spaces and the W. I checked in the debugger and the values of power.sensor_1, ... are always correct and are non zero.
The power values are all of the type double.
The function PAC1934_read_Power_accumulation(); returns a element of type PAC1934_ResultData_t with values for all the elements of it.
What is going wrong?
When I am rewriting the code with an integer, the sprintf works fine.
EDIT: Simple code just trying to output a float or a double doesn't work. Only integer output works. I have tested it with
double test = 1.432;
printf("%f",test);

Candidate problems:
No FP support #Tom V
Various compilers/linkers do not include floating point (FP) support automatically. Code with only FP via printf()/scanf() gets fooled into thinking no FP support needed. Research your compiler to force linking of FP support or maybe simple and some obvious FP code to your source code.
Buffer overrun
sprintf((char*)&buf, " %010.9f W ... may overrun. Is is good practice to be prepared for unexpected FP values and insure no overrun, not matter what. buf[100] with %010.9f is not enough.
Alternatives: #SparKot
// Limit buffer writing
snprintf((char*)&buf, sizeof buf, " %010.9f W ...
// or
// Use `%g` to avoid long text
sprintf((char*)&buf, " %010.9g W ...
// or
// Increase buffer size to some worst case - think -DBL_MAX
uint8_t buf[4 * 350] = {0};
True failure? #M.M
OP only described a failure, but did not post the code that could replicate it.
General help
Enable all compiler warnings.

Related

Passing pointer from Microsoft Visual C++ to Fortran and back after changing code from 32 bit to 64 bit [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
Improve this question
In Fortran a C function is called (compiled in Visual Studio 64 bit):
SUBROUTINE GET_PNTR
INTEGER*8 NXLOC(41)
REAL*4 WRX25I(41)
NXLOC(1) = IVRLOC( WRX25I(1) )
RETURN
END
With the C function defined as:
long long IVRLOC(var)
void *var;
{
return var;
}
When I stop at the return statement, var is defined as
FORTRAN_X64.exe!0x00007ff6de5b8074.
Converting the address to big endian gives 32758 -564428684
Converting the address to little endian gives -159449088 1954569182
When I step out of the function only the last 4 bytes (-564428684 in this case) of the big endian are shown for the value of NXLOC(1). I'm not sure if this is right or not, but it seems like it can't be and since the next step to use the address fails that it is incorrect seems confirmed. From searching the web it seems like the value should be little endian, but that is not what I'm seeing.
What is going on?
The next step in the Fortran code, when the address is used, looks like:
PROGRAM USE_PTR
INTEGER*8 NXLOC(41)
REAL*4 XSLAM(41)
NX = 41
CALL VALOCX(NXLOC(1),XSLAM(1),NX)
RETURN
END
Where the C function looks like:
void VALOCX( nsloc, vals, ns)
float *nsloc[], vals[];
int *ns;
{
int i;
for (i=0; i<*ns; i++) {
vals[i] = *nsloc[i];
}
}
nsloc in this function now has the value
0x00007ff6de5b3c00 {FORTRAN_X64.exe!CHKSUB} {0xffffffffde5b8074 {???}} where only the last four bytes of the original variable address is recovered. I'm assuming I need to convert from big endian to little endian at some point, but my efforts so far only seem to add to my confusion.
Why doesn't "var" convert to the correct value when exiting IVRLOC so that it converts back to the correct value in VALOCX?
If you are not declaring IVRLOC as a function returning INTEGER*8 (or maybe INTEGER(c_intptr_t) ) on the Fortran side, it's of type default integer which will likely be a 4-byte integer. Which could explain half of the original 8-byte value being set to zero due to the type mismatch.

Errors using fclose() [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I have a section of code that fails when I try to use fclose to close an output file. The code looks as follows:
void WriteArrayForCheck(int numLines, double **Array) {
char outFile2[300];
sprintf(outFile2, "OutputArray.txt");
FILE *outputFile2;
outputFile2 = fopen(outFile2, "w");
int incRow;
for (incRow = 0; incRow < numLines - 1; incRow++) {
fprintf(outputFile2, "%lf,%lf,%lf\n",
Array[incRow][1], Array[incRow][2], Array[incRow][3]);
}
fclose(outputFile2);
}
I end up with an error related to my executable that says:
free(): invalid next size (normal): 0x0000000001ce1710 ***
and a whole bunch of other stuff that doesn't make sense... The ironic thing is if I comment out the line related to fclose, then the program does not crash and runs perfectly fine... I have not had this issue before. I am sure that my matrices are incremented properly as well. PLease let me know what you think.
The code as posted does not seem to have an obvious problem.
Note however that:
You should always check the return value of fopen() and report failure instead of risking undefined behavior by passing NULL to fprintf and/or fclose.
You should simplify the first few statements as FILE *outputFile2 = fopen("OutputArray.txt", "w");
If you do something more complicated to compute the filename, post it as the problem may lie in seemingly harmless code that you omitted.
The fprintf conversion specifier for double is %f, the l modifier is useless and ignored in this context. It is required in fscanf() to distinguish between float and double, but not needed in fprintf because float values are always passed as double to variable argument functions.
The index values 1, 2 and 3 might be incorrect, arrays are 0 based in C.
Stopping the loop at incRow < numLines - 1 is unexpected too, why omit the last row of the matrix? If you really mean it, a comment would be helpful to clarify why.

C stringification: convert constant to integer [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I need to convert defined constants to their integer values so I came up with this macro (STR_TO_CONST) for doing so...
#define STRFY_VAL(s) #s
#define STRFY_KEY(s) STRFY_VAL(s)
#define STR_TO_CONST(s) atoi(STRFY_KEY(s))
It works, but I'm wondering if there are any potential problems with it as I've never encountered this macro before despite having searched considerably for something like it.
The reason you never encountered this is that it's utterly pointless, but let's explain by example. Say you have the following:
#define FINALANSWER 42
// ...
int x = 2 * STR_TO_CONST(FINALANSWER);
now, this is semantically no different from:
int x = 2 * FINALANSWER;
That's because preprocessor macros are ultimately just textual replacement happening before you actually compile. Therefore, FINALANSWER is just as good as an integer constant as 42 is.
Your "solution" to a non-existing problem just adds overhead in that it adds a new string constant to your code and an unnecessary function call as well.
I'm wondering if there are any potential problems with it (?)
Yes. Using atoi() to initialize a global results in something like "error: initializer element is not constant"
int x = STR_TO_CONST(123); // error
int y = 123; // no error
int main(void) {
return x + y;
}
Hide warnings. Only 1 line generated a useful warning
"warning: overflow in implicit constant conversion [-Woverflow]"
int main(void) {
int a = STR_TO_CONST(123456789012345); // no warning
int b = 123456789012345; // warning
return a + b;
}
Range issue. With 32-bit int, the below will likely exceed atoi() range resulting in undefined behavior with no warning.
int main(void) {
long long z = STR_TO_CONST(123456789012345);
return !z;
}

increment in while loop doesn't work? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
I am doing the following while loop, and the line number doesn't get incremented (it's always 0). Why is that?
int main(int argc, const char* argv[])
{
int line_number = 0;
int f = 0;
while (f == 0) {
printf("LINE NUMBER IS %f\n", line_number);
line_number++;
}
return EXIT_SUCCESS;
}
(I realize this is an infinite loop, but I am interested here in why line_number isn't getting incremented.)
With printf, it matters what letter you put after a % sign for variable replacement. If you look at the list of format specifiers, you’ll see that %f is for floating-point numbers. This means it thinks line_number is a float; it doesn’t do the proper conversion because it doesn’t realize it needs to, and instead just reads the same bits as a float.
The way the floating-point format works is complicated, but you’ll stay very close to zero for a very long time. Depending on how fast your computer is and how patient you are, you might or might not see it change if you leave it running for longer.
(Technically it’s even worse than this, as this is undefined behavior; however, this is the most likely outcome.)
Most compilers will have some option to warn you if you use the wrong format specifier; you should probably turn on the default set of compiler warnings so it can tell you about this and other issues.

Float not being converted correctly [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am working on a program that will convert from dollars to cents. I take in user input as a float using a predefined function then i try to multiply this float by 100 but it gives me an incorrect value. Heres the code:
printf("Change in dollars: ");
change= GetFloat();
cents= round(change*100);
printf("Cents is %f",cents);
This is a logical error because the program runs fine but there is something wrong with the mathematics for example if i enter 1.50 when prompted, the return i get is 1004 which is clearly wrong. What i want to happen is 150 to be outputted.
This is most likely because you have some locale where the decimal separator is , instead of ., and since you are very likely not checking the return value of scanf() "which is what most books do and almost every tutorial", then the variable is not being initialized and what you are printing is a consequence of the layout of your program instead of a value inputed by a user.
To verify what I say, I suggest compiling the same program without modification but with different compilation flags.
What you must do is ensure that the input is correct, try this
float GetFloat(int *ok)
{
float value = 0;
if (scanf("%f", &value) != 1)
*ok = 0;
else
*ok = 1;
return value;
}
which you would call like this
int result = 0;
float change = GetFloat(&result);
if (result == 0)
return -1;
float cents = round(change * 100);
printf("Cents is %f",cents);
If the decimal separator is an issue, the above program will not output anything, because scanf() will return 0, and hence ok will be 0 after you call the function.
One important consequence of ignoring the return value of non-void functions is that if the value was not initialized like in this case with scanf(), and you don't know that because you didn't check the return value, then undefined behavior will happen, meaning that your program will contain bugs that are very difficult to find and hence very hard to fix.

Resources