Why does the compiler complain about this `sprintf` argument? - c

The following code used to compile fine. I migrated the project to a new version and now the compiler is complaining about one of my sprintf arguments. Here is the warning:
warning: format '%02d' expects type 'int', but argument 12 has type 'double'
FYI, the IDE is MPLAB X 2.35 and the compiler is XC 1.34. I have optimizations turned off and I have tried clean/build. I can only suspect that maybe the struct alignment is out of whack. I am hoping I am just missing the obvious, such as not being able to count.
Offending code:
typedef struct _AnalysisEvent
{
unsigned short id;
unsigned char day;
unsigned char month;
unsigned char year;
unsigned char hour;
unsigned char minute;
unsigned char second;
unsigned int duration;
double min;
double max;
double avg;
} AnalysisEvent;
AnalysisEvent AnalysisEvents[ANALYSIS_MAX_COUNT][ANALYSIS_EVENTS_MAX_COUNT];
unsigned char AnalysisEventGetValueStrAlt(unsigned short id, unsigned char index, char *buffer, int length)
{
if (Analysis[id].count > index)
{
sprintf(buffer, "Analysis ID: %d\r\nEvent ID: %d\r\nMin: %.2f\r\nMax: %.2f\r\nAvg: %.2f\r\nTime: %02d/%02d/%02d %02d:%02d:%02d\r\nDuration: %d\r\n",
id,
index,
AnalysisEvents[id][index].min,
AnalysisEvents[id][index].max,
AnalysisEvents[id][index].avg,
AnalysisEvents[id][index].month,
AnalysisEvents[id][index].day,
AnalysisEvents[id][index].year,
AnalysisEvents[id][index].hour,
AnalysisEvents[id][index].min,
AnalysisEvents[id][index].second,
AnalysisEvents[id][index].duration
);
return index;
}
else
{
return 0;
}
}

Argument 12 is:
AnalysisEvents[id][index].min,
You probably want:
AnalysisEvents[id][index].minute,

In your case, the offending part is
%02d/%02d/%02d %02d:%02d:%02d\r\
^^^
The corresponding argument is AnalysisEvents[id][index].min, type double. You used %d.
FWIW, maybe the answer you want is
"the argument number in the warning message is the total of the ones supplied to sprintf(), counting from buffer itself, not only the ones supplied as the argument to the format."

Related

assign zero in unsigned short int in c

I try to assign zero to a field in a structure called list
list.ultimo = 0;
but when I use printf
printf("%d", list.ultimo);
I get the result
32766
but when I add
unsigned short int cero = 0;
the result of printf is correct, no matter that does not use cero. why?
lista.h
#ifndef LISTA_H
#define LISTA_H
typedef struct{
elemento lista[TAMANOMAX];
unsigned short int ultimo;
}LISTA;
void Insertar(elemento, unsigned short int posicion, LISTA);
#endif
lista.c
#include<stdio.h>
typedef short int elemento;
#ifndef TAMANOMAX
#define TAMANOMAX 10
#endif
#include"lista.h"
void Insertar(elemento x, unsigned short int p, LISTA lista){
if (lista.ultimo >= TAMANOMAX){
puts("full list");
printf("%hu",lista.ultimo);
}
}
main.c
#include<stdio.h>
typedef unsigned short int elemento;
#define TAMANOMAX 4
#include"lista.h"
int main(){
LISTA esferas;
esferas.ultimo = 0;
Insertar(2,0,esferas);
printf("\n%hu\n", esferas.ultimo);
return 0;
}
the result is
$gcc -Wall lista.c main.c
full list
32765
0
I'm new to this, I'm slow for now, I regret the delay
Use %hd to print a short int and %hu to print an unsigned short int. %d is for int.
EDIT: Now that you have posted the full code, it appears that TAMANOMAX is set to 10 in lista.c, but set to 4 in main.c, leading to an incompatibilty between your main() function and the Insertar one. You should have the same value in all files. And if you want to work with different array lengths, add a length member in your LISTA structure. But TAMANOMAX should absolutely be the same everywhere, else you're in fact working with different data types and your program won't work.
Using mismatched format specifier with the type of the argument invokes undefined behavior.
Quoting C11 standard, chapter §7.21.6.1, fprintf() function
[..] If any argument is
not the correct type for the corresponding conversion specification, the behavior is
undefined.
and about %d format specifier,
d,i The int argument [....]
so, %d expects an int.
As per your question title, ultimo is unsigned short int and you're using %d to print the value.
You should use %hu to print unsigned short int.

Program crashes when reading first data point

I want to see what student have the best mark in the class.
So I make this ,but i don't know where I am wrong
struct Date {
char name[31];
float mark;
};
struct Date * Read(unsigned int n,struct Date *d){
int i;
for(i=0;i<n;i++){
getchar();
fgets(d[i].name, 31, stdin);
scanf("%f",d[i].mark);
}
return d;
}
int main(){
unsigned int n;
struct Date *d;
scanf("%u",&n);
d = (struct Date*) malloc(n*sizeof(struct Date));
d=Read(n,d);
free(date);
return 0;
}
after i read the mark the program crash.
Can someone help me and explain what to change?
Thanks a lot.
The crash is most likely due to this:
scanf("%f",d[i].mark);
You should pass the address as argument to read a float value. It should be:
scanf("%f", &d[i].mark);
Technically, this is undefined behaviour..
Compile with all warnings enabled. gcc warns even without any specific options:
warning: format %f expects argument of type âfloat *â, but argument 2 has type double [-Wformat=]
scanf("%f",d[i].mark);

printf char as hex in c

I expect ouput something like \9b\d9\c0... from code below, but I'm getting \ffffff9b\ffffffd9\ffffffc0\ffffff9d\53\ffffffa9\fffffff4\49\ffffffb0\ffff
ffef\ffffffd9\ffffffaa\61\fffffff7\54\fffffffb. I added explicit casting to char, but it has no effect. What's going on here?
typdef struct PT {
// ... omitted
char GUID[16];
} PT;
PT *pt;
// ... omitted
int i;
for(i=0;i<16;i++) {
printf("\\%02x", (char) pt->GUID[i]);
}
Edit: only casting to (unsigned char) worked for me. Compiler spits warnings on me when using %02hhx (gcc -Wall). (unsigned int) had no effect.
The reason why this is happening is that chars on your system are signed. When you pass them to functions with variable number of arguments, such as printf (outside of fixed-argument portion of the signature) chars get converted to int, and they get sign-extended in the process.
To fix this, cast the value to unsigned char:
printf("\\%02hhx", (unsigned char) pt->GUID[i]);
Demo.
Use:
printf("\%02hhx", pt->GUID[i]);
Because printf() is a variadic function, its arguments are promoted to int. The hh modifier tells printf() that the type of the corresponding value is unsigned char and not int.
Cast to unsigned char instead, to avoid a leading 1 bit being interpreted as a negative value.
I noticed that you were getting the F's when the number was larger than 99x.
I wrote this to test it out and discovered the hh prefix at http://www.cplusplus.com/reference/cstdio/printf/
#include "stdio.h"
char GUID[16];
int main() {
int i;
for(i=0;i<16;i++) {
GUID[i]=i*i;
}
for(i=0;i<16;i++) {
printf("\\%02.2hhx\n", GUID[i]);
}
return 0;
}
Use a small own implementation to solve this problem on all platforms:
char hex[] = "0123456789abcdef";
void printHex(unsigned char byte) {
printf("%c%c", hex[byte>>4], hex[byte&0xf]);
}

Strange int output in C

I am using OpenCV and I need to convert Iplimage->ID to char[ ] so that I can send it using TCP and then reconvert it to int on the server.
Here is the Iplimage header:
typedef struct _IplImage
{
int nSize;
int ID; //<--- ID of type INT
int nChannels;
int alphaChannel;
int depth;
char colorModel[4];
char channelSeq[4];
int dataOrder;
int origin;
int align;
int width;
int height;
struct _IplROI *roi;
struct _IplImage *maskROI;
void *imageId;
struct _IplTileInfo *tileInfo;
int imageSize;
char *imageData;
int widthStep;
int BorderMode[4];
int BorderConst[4];
char *imageDataOrigin;
}
IplImage;
this is my code:
char IDbuffer[10];
snprintf(IDbuffer,10,"%e",frame->ID);//where frame is of type IplImage*
printf("frame->ID= %a\n",IDbuffer);
and this what I got printed:
frame->ID= 0x0.0000000037d0cp-1022
even trying
printf("frame->ID= %a\n",frame->ID);
give me the same output.
Is this an integer format ?? and if yes how could I convert the char * of this format to an int??
Thanks in advance.
Use the %d format specifier since frame->ID is an integer:
snprintf(IDbuffer,10,"%d",frame->ID);
And then use the %s format specifier to print the buffer:
printf("frame->ID= %s\n",IDbuffer);
There's more information about the format specifiers in printf man page.
%e format specifier requires an argument of type double, while you are passing an int instead. The resultant behavior is undefined. That's all there is to it.
By using %e you are making a promise to snprintf. You promise that you will supply a double argument in the corresponding position. Later you break that promise by supplying an int instead of double, which leads to a meaningless result. You are essentially lying to snprintf about the type of frame->ID.
%a also requires a double argument. Why do you insist on using double format specifiers with a int argument? How do you expect this to work?
Either supply an argument of correct type (which is double), or use the proper format specifier (which is %d for int). Either this or that. Mixing things up like you do will not achieve anything.
You need cast ID to double before printing it:
snprintf(IDbuffer,10,"%e", (double)frame->ID);
Alternatively, you can print it as integer:
snprintf(IDbuffer,10,"%d", frame->ID)
Check this for more information on snprintf

Incorrect results from function which is using unsigned long long int

The following is the code which I typed in c
unsigned long long int Je=23;
int col=2,row=2;
void mod(unsigned long long int mat1[][col],unsigned long long int mat2[][col],int r)
{
int i,j;
for(i=0;i<r;i++)
for(j=0;j<col;j++)
{
mat1[i][j]=mat2[i][j]%Je;
printf("Value mat1=%u mat2=%u Je=%u\n",mat1[i][j],mat2[i][j],Je);
}
}
I call this function with the following matrix
t1[2][2]={1036,1090,1526,1472};
mod(t2,t1,row);
But in the console screen I get the following results for the "printf" statement I included inside the function definition
Value mat1=5 mat2=0 Je=1036
Value mat1=2 mat2=0 Je=1090
Value mat1=16 mat2=0 Je=1526
Value mat1=9 mat2=0 Je=1472
How come the values are printed like this? I am using Dev Cpp compiler.
The format specifiers "%u" in the printf statement are incorrect. For an unsigned long long, the specifier should be "%llu"

Resources