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.
Related
I'm making a program that has 3 files: 2.c, 2tele.c, tele.h
2.c
#include <stdio.h>
#include <stdlib.h>
#include "2tele.c"
int main(void){
TELEFONE tf = preenche_telefone(tf.numero, tf.nome);
mostra_telefone(tf);
}
2tele.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tele.h"
void mostra_telefone(TELEFONE tf){
printf("\nNumero = %d\nNome = %s", tf.numero, tf.nome);
}
TELEFONE preenche_telefone(char nome[], int numero){
TELEFONE tf;
printf("Introduza o numero\n");
scanf("%d", numero);
tf.numero = numero;
printf("Introduza o nome\n");
scanf("%s", nome);
strcpy(tf.nome,nome);
return tf;
}
tele.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct contacto{
int numero;
char nome[100];
}TELEFONE;
void mostra_telefone(TELEFONE tf);
In line 6 of 2tele.c I'm getting the error multiple definition of 'mostra_telefone', however I have read other posts and have also defined it on tele.h.
What should I do?
Edit: When i include "tele.h" instead of "2tele.c" it says that "TELEFONE tf = preenche_telefone(tf.numero, tf.nome);" has a bad initializer
In line 6 of 2tele.c I'm getting the error multiple definition of 'mostra_telefone',
That's a misleading claim. You might get such a message when you attempt to link the program, but that would be a function of the details of your build procedure. You appear to have cherry-picked a detail of the diagnostic that does not convey the nature of the problem. Always give us an exact copy of the full diagnostic message.
however I have read other posts and have also defined it on tele.h.
No, you haven't. You have declared it in tele.h, which is in fact exactly what you should do. And every source file that references that function should #include the header, to get only a declaration, and avoid #includeing 2tele.c, which would provide a[n additional] definition. For functions, the difference is that a definition includes the function body.
Including the .c file instead of the .h file means that 2.c provides a definition of mostra_telefone(). If you compile 2.c to create an object file and also compile 2tele.c to create an object file, or if you compile both together to build a program directly, then each one provides a definition. It does not matter that the two definitions are lexically identical, or that they ultimately are derived from the same source file. There can be multiple declarations of the function, in the same or different translation units, but in the whole program, as compiled, there can be only one definition.
Solution: no file #includes 2tele.c. All that want to access the functions defined within instead declare those functions before use without defining them (except 2tele.c itself). The conventional way to do this is to #include a header containing the needed declarations -- in your case, that's tele.h.
But you say,
When i include "tele.h" instead of "2tele.c" it says that "TELEFONE tf = preenche_telefone(tf.numero, tf.nome);" has a bad initializer
Turn up your compiler's warning level. With gcc and other compilers that understand its options, for example, turn on at least -Wall. That should clue you in to the root of this problem:
2.c: In function ‘main’:
2.c:6:5: warning: implicit declaration of function ‘preenche_telefone’ [-Wimplicit-function-declaration]
TELEFONE tf = preenche_telefone(tf.numero, tf.nome);
That arises because there is no declaration of preenche_telefone() in tele.h. It is an error for main() to attempt to call that function without an in-scope declaration for it, but for historical reasons, many compilers accept the call and try to guess a declaration. That guess will invariably assume that the function's return type is int, and an int is not a valid initializer for a struct such as your TELEFONE.
Solution: Add the needed declaration of preenche_telefone() to tele.h.
I am trying to learn the use of the extern keyword. As an example I am using the getopt C library function. From my understanding of the extern keyword, it used to indicate to the compiler that a certain variable that has been defined in another file is going to be used. So whenever I am going to be using the getopt variables like opterr, optind, etc, should I(would it be wrong of me to) do this:
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
extern int optopt;
extern int opterr;
extern int optind;
extern char *optarg;
int main(int argc, char **argv) {
/* code using getopt */
}
When I looked at the manpage for getopt(3), I saw these declarations already mentioned under #include <unistd.h>. So I thought that these were declared in that header file but when I looked into the header file itself, there was no such declaration.
So my question is: is there anything wrong with using these statements at the beginning even if for the sake of improving readability for someone who doesn't how getopt works. Also, at the end of the day if the linker is going to resolve references, anyways, is there any reason to use extern at all?
Also, at the end of the day if the linker is going to resolve references, anyways, is there any reason to use extern at all?
The extern keyword can tell the compiler that an unknown symbol is going to be provided by another file.
Consider the situation where we have file1.c with:
int myvariable;
And file2.c with:
#include <stdio.h>
int main() {
myvariable = 10;
printf("myvariable is %d\n", myvariable);
return 0;
}
Attempting to compile this will fail with:
file2.c: In function ‘main’:
file2.c:4:5: error: ‘myvariable’ undeclared (first use in this function)
4 | myvariable=10;
Adding the appropriate extern declaration to file2.c allows us to compile it without errors:
#include <stdio.h>
extern int myvariable;
int main() {
myvariable = 10;
printf("myvariable is %d\n", myvariable);
return 0;
}
Header files can be nested.
unitstd.h includes many other files, the specific declarations you are looking for are in getopt.h,
These statements do not improve readability, they decrease it by adding duplicate garbage code.
A programmer familiar with C but not with getopt function would think these are your custom variables, not part of the standard library, because nothing in the standard library should be redeclared.
The linker is the last step in building the executable.
The external keyword is for the compiler to know the names and types, so it can build code with references for the linker to resolve later.
While it's OK to have more than one declaration for a function or object, as a rule it's best not to redeclare anything declared in a standard library header. It might cause issues if what you declared doesn't exactly match what's in the headers.
Also, just because the man pages say to include unistd.h doesn't necessarily mean the declaration is in that specific file. The declaration in question could be in a file that unistd.h includes. All it means is that including unistd.h will give you the required declaration.
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
This question already has answers here:
Weird compilation error in Visual Studio 2008
(7 answers)
Closed 8 years ago.
I have a simple c program (It's a base program without any GUI) ,
on linux this code compiles and runs without any issue with gcc compiler, now I have to compile the same code on windows with Visual Studio 2013, with both visual c and intel compilers, I have selected new console application program following this guide
but get tons of these error messages
error : declaration may not appear after executable statement in block myfile.c
at all the line with variables declarations, (also on a simple int i; )
the only libraries that I use are these
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <xmmintrin.h>
#include <math.h>
#include <string.h>
Any suggestion?
It seems that your program has Mixed Declarations and Code. VS doesn't support mixed type declaration (or you can say it doesn't support C99 completely).
In mixed declarations and code, for example, you could do:
int i;
...
i++;
int j = i + 2;
Each identifier is visible from where it is declared until the end of the enclosing block.
You need to move all the declaration to the beginning just like in C89. And you should note that VS is not a C compiler.
The problem is with code such as this:
void foo()
{
bar(); /* statement */
int i; /* variable declaration */
}
That is not C90 valid, because there declarations must be at the beginning of the block, just after the opening brace ({).
In C99 and later it is correct, however, so GCC accepts it, (C90 is 15 years old).
Unfortunately MS-VC does not, and will not, support C99, so your code will not compile there.
You can fix it manually, by moving the declaration to the top of the block (1), add a lot of braces (2), try to compile it as C++, of change the compiler... that's up to you!
Example 1:
void foo()
{
int i;
bar();
/* beware! if i was initialized, add the initialization here, not there */
}
Example 2 (hidden braces):
void foo()
{
bar();
{int i;
}} /*all the closing braces should be at the end of the function */
I'm compiling a C program which includes sybdb.h and I get the error "two or more data types in declaration specifiers" at the typedef line below (and sybdb.h is a standard file, not one of mine).
#if !defined(_WINDEF_) && !defined(_WINDEF_H) && !defined(DOS32X)
typedef int BOOL;
#endif
It appears that there is some kind of a conflict with another library I am including, but have no idea what the error means or how to fix it. Help?
Most likely another header (or your implementation of C itself) has done something like:
#define BOOL unsigned char
so that your compiler is seeing:
typedef int unsigned char;
By way of experiment, when I compile the code:
#define XYZZY unsigned char
typedef int BOOL;
int main (void) {
return 0;
}
it works fine but, when I change that first line to #define BOOL unsigned char, I get the exact same message you see:
qq.c:2:17: error: two or more data types in declaration specifiers
qq.c:2:5: warning: useless type name in empty declaration
To confirm this, you can compile only the pre-processor phase to see what that code really looks like to the compiler phase.
This depends on the compiler, of course, gcc -E is the option you would use for gcc.
Fixing it is another matter. You may well have to change one of the alias types to BOOL1 or something incredibly ugly like that. That's likely to be a larger change since I imagine it would be used quite a bit.
You may be able to get away with simply ensuring both subsystems use the same definition of BOOL but it will still take quite a bit of analysis to confirm that this won't have adverse side effects.
To test (and even possibly implement) this fix, you can change the #if statement to something like:
#ifndef SKIP_BOOL_DEF
#if !defined(_WINDEF_) && !defined(_WINDEF_H) && !defined(DOS32X)
typedef int BOOL;
#endif
#endif
and then compile your code with gcc -DSKIP_BOOL_DEF (or equivalent) to ensure the typedef isn't done. It would then use your (hopefully compatible) system definition.