c sscanf and SCNu64 compile error - c

I don't understand the below error message when I compile this code. I couldn't find out what wrong with it.
Description Resource Path Location
Type expected ‘)’ before ‘SCNu64’.
#include <inttypes.h>
int calc_rate(uint64_t *rate, char val[], char mult[]) {
int rc = sscanf(val, "%" SCNu64 "%2s", rate, mult);
}

If you have both <inttypes.h> and <stdio.h> included, then the code fragment shown compiles cleanly. (You can't call sscanf() legally unless there's a prototype in scope.) That means the problem is in the code prior to what you are showing. Or it means that your compiler doesn't provide support for exactly 64-bit types, which is rather unlikely unless you're on a relatively obscure mainframe, or you aren't compiling in C99 or C11 mode.

Related

Can't set value of structure variable

I have a structure defined in quaternions.c
typedef struct quaternion{
double arr[4];
} quaternion;
with header file
#ifndef QUATERNIONS_H
#define QUATERNIONS_H
typedef struct quaternion{
double arr[4];
} quaternion;
#endif
Since this is my first time using C structures, I tried testing it out.
#include <stdio.h>
#include "quaternions.h"
int main(){
quaternion a;
a.arr[1]=2.5;
printf("%d\n",a.arr[1]);
return 0;
}
As far as I can tell, what I'm doing is almost identical to this article. However, when I compile and run this, it prints a random gibberish number. What am I doing wrong?
The correct printf conversion format specifier for a double is %f, not %d. See the documentation for that function for further information.
You should change the line
printf("%d\n",a.arr[1]);
to:
printf("%f\n",a.arr[1]);
By using the wrong conversion format specifier, your program is invoking undefined behavior. This explains why your program is printing "random gibberish" instead of the desired output.
Most good compilers will warn you if you use the wrong conversion format specifier. If your compiler doesn't warn you, then I suggest that you make sure that you have all warnings enabled. See this question for further information:
Why should I always enable compiler warnings?

why is this behaviour of strtof() changes with respect to the change in stdlib.h?

With <stdlib.h> included the following code gives the output of 123.34.
#include<stdlib.h>
int main()
{
char *str="123.34";
float f= strtof(str,NULL);
printf("%f",f);
}
But without <stdlib.h> it produces the output of 33.000000.
What is the role of <stdlib.h> here and why did the value 33.00000 occur when it is nowhere in the code?
You must take a look at the warning generated by the compiler.
warning: implicit declaration of function 'strtof' [-Wimplicit-function-declaration]
This still yields result, which is not deterministic in any way because the return type expected is float, whereas without the header inclusion, the default is assumed to be int.
If you look into the stdlib header file, there is a declaration,
float strtof(const char *restrict, char **restrict);
With #include<stdlib.h>, we provide this declaration. When missed, compiler assumes to be returning int, and hence the result is not deterministic.
With my system, it produced 0.00000000 as the output, whereas with the necessary inclusions, I got 123.339996 as the output.
As a precaution, make a habit of always compiling the code with -Wall option (Assuming that you are using gcc), or better yet, -Werror option.
The <stdlib.h> header tells the compiler that strtof() returns a float(); in its absence, the compiler is forced to assume it returns an int. Modern C compilers (GCC 5 and above) complain about the absence of a declaration for strtof() and/or a conflict with its internal memorized declaration for strtof().
If you omit <stdlib.h>, your code is unacceptable in C99 and C11 because you didn't declare strtof() before using it. Since you omit <stdio.h>, it is invalid in C90, let alone C99 or C11. You must declare variadic functions such as printf() before using them.

aligned_alloc return assignment warning

I am cleaning up warnings and found the following error:
warning: assignment makes pointer from integer without a cast buf = aligned_alloc(ALIGN_VALUE,BUF_SZ);
This call is at the very top of the function, essentially:
char* buf;
buf = aligned_alloc(ALIGN_VALUE,BUF_SZ);
It is my understanding that aligned_alloc returns a void *. If cast the return from aligned_alloc to a (char *) I get:
warning: cast to pointer from integer of different size [-Wint-to-pointer-ast] buf = (char*)aligned_alloc(ALIGN_VALUE,BUF_SZ);
The only thing that seems to fix it is
buf = (char*)(uintptr_t)aligned_alloc(ALIGN_VALUE,BUF_SZ);
I have made sure that I am including stdlib.h to avoid implicit declarations referred to in another post. I assumed the cast to char pointer should have resolved this. I am not understanding why the cast to uintptr_t resolves it when void* and uintptr_t are equivalent as far as I understand.
The following is an example of the structure of the file
#include <syslog.h>
#include <linux/fs.h>
#include <linux/hdreg.h>
#include <sys/ioctl.h>
#include <sys/mman.h> // mmap
#include <sys/time.h>
#include <unistd.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <stdio.h>
#include <pthread.h>
void* ax_read_thread(void* arg)
{
fprintf(stderr, "read thread started\n");
ax_priv* priv = (ax_priv*)arg;
char* buf;
uint32_t count = 0;
size_t len, transferred = 0;
buf = (char*)(uintptr_t)aligned_alloc(ALIGN_VALUE,BUF_SZ);
if (buf == NULL){
fprintf(stderr, "Aligned alloc failed\n");
pthread_exit(NULL);
}
while(1){
//do things
}
}
Thank you for all of the help. I see now that the warning is a result of not indicating the proper version when invoking the compiler.
This answer largely summarizes the observations and suggestions from the comments thread, including mine and many others', and wraps them in a bit of expository prose.
In the first place, the problem arises because when you build your program with your present toolchain, in its current form, the aligned_alloc() function is not explicitly declared. In the absence of a declaration, the compiler is inferring its signature: it guesses that the function returns int, and that its parameter types are those obtained via the default argument promotions applied to the types of the actual arguments. The compiler then warns you that those inferences -- especially the return type -- seem inconsistent with how you're actually using the function.
The solution, supposing that the function is available in your C library at all, is to ensure that a correct prototype is provided. You could insert the prototype manually, but you shouldn't. Since it's a standard library function, you should get its declaration from the appropriate header, which for this function is stdlib.h.
HOWEVER, this particular function is new in C11, and evidently you're using a version of GCC that defaults to compiling for an earlier standard. Glibc supports that in part by protecting functions that are new in C11 with a feature-test macro, _ISOC11_SOURCE. This is for your protection: in the event that you're building code written for an earlier standard, and that code happens to provide is own function with the same name as one of C11's new functions, the feature-test system prevents you from suffering a name collision.
If you are indeed writing for C11, as seems to be the case, and if your version of gcc has an option to support C11 (i.e. -std=c11 and/or -std=gnu11), then compiling with that option enabled is your best alternative. If you happen to have a version of Glibc that provides aligned_alloc() but not a version of the compiler that supports a C11 mode, then you have the alternative of manually ensuring that the needed feature test macro is defined to the compiler before any of the standard headers are included. You can do that via a #define at the top of your source file, or via a command-line option to the compiler (e.g. -D_ISOC11_SOURCE=1).
Glibc does have aligned_alloc() from at least version 2.17 (but I think from as early as 2.16). GCC does have a C11 mode since at least version 4.8. If your versions of these components are at least that recent, then it should be sufficient to add the option -std=c11 (to omit GNU extensions) or -std=gnu11 (to support GNU extensions) to your compilation command:
gcc -std=c11 my_program.c

Is "small" a keyword in c?

This is the first code
#include <stdio.h>
#include <conio.h>
int main()
{
int small;//showing error-(two or more data type in declaration specifiers
}
This is the second code
#include <stdio.h>
int main()
{
int small;//normal declaration without any error
}
Whenever I include header file <conio.h> then declaring a identifier "small" gives an error, why?
I am using mingw gcc compiler and codeblocks ide
Also I have added following code in <conio.h>
#include <windows.h>
void gotoxy(short int col,short int row)
{
HANDLE hStdout=GetStdHandle(STD_OUTPUT_HANDLE);
COORD position={col,row};
SetConsoleCursorPosition(hStdout,position);
}
after removing above code from <conio.h>
int small;
works even after including <conio.h>.
I guarantee that small is not a keyword in C. If it were, the presence or absence of a #include directive would not make any difference.
The problem is that <windows.h> stupidly defines small as a macro. (Other answers and comments suggest it might be a typedef, but that wouldn't explain the problem you're seeing.)
I'm able to reproduce the problem on my system (Cygwin, Windows 7, compiling with mingw32-gcc, which is installed as part of the Cygwin package). Presumably the same thing would happen with MinGW installed separately from Cygwin.
First of all, <conio.h> is a (non-standard) header provided by the implementation. You almost certainly shouldn't be trying to modify it. You definitely shouldn't be adding a function definition to a header file (function definitions belong in .c files, not in .h files). If you want to write your own gotoxy function, declare it in your own header and define it in your own .c file; don't mess around with the implementation. (B
But when you added your gotoxy function to <conio.h>, you also added
#include <windows.h>
Here's a small program that illustrates the problem:
#include <windows.h>
int main()
{
int small;
}
When I compile this with mingw32-gcc, I get:
c.c: In function 'main':
c.c:4:9: error: two or more data types in declaration specifiers
c.c:4:5: warning: useless type name in empty declaration [enabled by default]
Digging further, it turns out that <windows.h> includes <rpcndr.h>, which contains the following:
#define small char
So every occurrence of the identifier small in any C source that has #include <windows.h> will be replaced by the keyword char -- which, in your case, will cause a syntax error.
A handy way to find things like this: gcc has a -E option that causes it to show the output of the compiler's preprocessor phase. With the above program, I tried this:
$ mingw32-gcc -E c.c | tail
#pragma pack(pop)
# 115 "c:\\gnustep\\bin\\../lib/gcc/mingw32/4.6.1/../../../../include/windows.h" 2 3
# 2 "c.c" 2
int main()
{
int char;
}
$
which shows how the int short; declaration was mangled by the preprocessor.
To be clear, this is entirely the fault of the maintainers of <windows.h> and <rpcndr.h>. small is a perfectly valid C identifier, and a system header absolutely should not define it as a macro. typedef char small; would have served the same purpose and not caused this problem. Others have had similar problems with <windows.h> defining macros min and max. That can be worked around with:
#define NOMINMAX
#include <windows.h>
but as far as I can tell there's no such workaround for small.
Incidentally, rpcndr.h also defines hyper.
The simplest solution is to call your variable something other than small -- and hope you don't collide with other macros defined in <windows.h>. Or you can add
#undef small
before the declaration. You shouldn't need to do either of these things, but thanks to poorly written system headers, such workaround are sometimes necessary.
Or just avoid including <windows.h> (that's not always possible).
(You could modify your copy of the rpcndr.h file, but I advise against doing so; it's likely to cause other problems, and your code still won't compile on a system where rpcndr.h hasn't been hacked.)
UPDATE : This may have been corrected. I don't see the error using x86_64-w64-mingw32-gcc under Cygwin on Windows 10. Perhaps someone else who uses mingw can investigate further.
No. There is no keyword like small in standard C. This may be a macro in <conio.h>.
C11: 6.4.1 Keywords:
keyword: one of
auto
break
case
char
const
continue
default
do
double
else
enum
extern
float
for
goto
if
inline
int
long
register
restrict
return
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while
_Alignas
_Alignof
_Atomic
_Bool
_Complex
_Generic
_Imaginary
_Noreturn
_Static_assert
_Thread_local
I found it...
its a macro defined in some header file which is included in windows.h.
as i have included windows.h in conio.h so in my program it is automatically included when i include conio.h.
I Found it by ctrl + clicking on small
By adding #include <windows.h>, you are pulling in a lot of other header files. One problem that has been reported is of it defining a preprocessor macro "small". It has also been discussed in another SO question.
One workaround is to add #undef small after you #include <windows.h>.
Just define WIN32_LEAN_AND_MEAN macro in code or VS Properties dialog and the problem will be gone:
#define WIN32_LEAN_AND_MEAN
The error seems to be the fault of MinGW. The same error appears with large.
There is no such keyword, but check if it is typedefed somewhere.

why is strtof is always evaluating to HUGE_VAL?

What could be the issue here? It doesn't matter what number I choose for str, it is always 26815615859885194199148049996411692254958731641184786755447122887443528060147093953603748596333806855380063716372972101707507765623893139892867298012168192.00
char *str = "2.6";
printf("%f\n", strtof(str, (char**)NULL));
//prints 26815615859885194199148049996411692254958731641184786755447122887443528060147093953603748596333806855380063716372972101707507765623893139892867298012168192.00
whole program:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *str = "2.6";
printf("%f\n", strtof(str, NULL));
return 1;
}
compile with -Wall:
test4.c:7: warning: implicit declaration of function âstrtofâ
What platform are you building for/on? The warning that you say is being emitted:
test4.c:7: warning: implicit declaration of function âstrtofâ
indicates that the compiler doesn't know that strtof() returns a float, so it's going to push an int to the printf() call instead of a double. strtof() is normally declared in stdlib.h, which you're including. But it wasn't a standard function until C99, so the exact compiler platform (and configuration/options you're using) may affect whether it's being made available or not.
strtof is defined in C99 only. It may be that passing the option -std=c99 to the compiler will fix it since default GCC (-std=gnu89) includes only a few C99 features.
Another option is to use the C89-kosher strtod. Which is probably the better option in the long run, anyways. (When do you need singles except in exceptional circumstances?)
Perhaps you've forgotten to include the correct header(s)?
#include <stdlib.h>
#include <stdio.h>
int main() {
printf("%f\n", strtof("2.6", NULL));
return 0;
}
produces:
2.600000
for me...
Given your warnings, you should try adding -std=c99 to get the C99 standard definitions from the header. By default it will assume that the return value is an int and then try to convert that to a float. This will obviously be wrong. Alternatively you could simply supply your own, correct declaration for strtof().
As the others have said, you need -std=c99. But you can also use strtod() which is string to double, and you don't need -std=c99 for that.
I was having problems with strtof() on CentOS 5.5 with glibc 2.5 unless I used -std=c99, but strtod() worked perfectly.

Resources