GCC typeof extension - c

I don't understand why this works:
/* gcc range extension */
__extension__ static int fn(int n)
{
switch (n) {
case 0: return 0;
case 1 ... 1000: return 1;
default: return -1;
}
}
But this does not:
/* gcc typeof extension */
__extension__ static void fn(int n)
{
typeof(n) a = n;
printf("%d\n", a);
}
gcc returns:
demo.c:14: warning: implicit declaration of function ‘typeof’
demo.c:14: warning: nested extern declaration of ‘typeof’
demo.c:14: error: expected ‘;’ before ‘a’
demo.c:16: error: ‘a’ undeclared (first use in this function)
demo.c:16: error: (Each undeclared identifier is reported only once
demo.c:16: error: for each function it appears in.)
I know I can compile with -std=gnu99 to avoid the error but the first one works with -std=c99 and uses also an extension

Non-ANSI compatible keywords are not ever reenabled by __extension__ (the only effect of __extension__ is warning suppression for -pedantic). Use __typeof__ if you want to compile in ANSI mode.

If you are writing a header file that must work when included in ISO C programs, write __typeof__ instead of typeof.
Refer to this link for a more elaborate description and the possible fixes.
Note: __extension__ has no effect aside from suppressing the warnings when using ANSI C -pedantic mode.
So something like this:
/* gcc typeof extension */
__extension__ static void fn(int n)
{
__typeof__(n) a = n;
printf("%d\n", a);
}

Related

Why does this compile in VS 2015 but not in IDEOne?

#include <stdio.h>
void foo(void);
void foo(int repeatCount) {
int i;
for (i = 0; i < repeatCount; i++) {
printf("\nHello World\n");
}
}
int main(int argc, char *argv[]) {
printf("main");
}
This is intended to be C, not C++. The file in VS is saved as a .c file, the program in IDEOne is configured as a C file.
The prototype doesn't match the function definition.
However, it does compile in VS 2015. Warning Level 3 does give a warning.
Because VS studio doesn't conform to the Standard C and uses its own compiler.
With Standard C you should see something like this:
gsamaras#gsamaras-A15:~$ gcc -Wall main.c
main.c:5:6: error: conflicting types for ‘foo’
void foo(int repeatCount) {
^
main.c:3:6: note: previous declaration of ‘foo’ was here
void foo(void);
^
main.c: In function ‘main’:
main.c:14:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
What compiler does VS use?
The compiler is named as Microsoft C/C++ Compiler. The cl.exe is a tool that controls the Microsoft C and C++ compilers and linker. There are other compilers you can use: Intel C and C++ Compilers, which is automatically configured in Visual Studio after installation.

Why is the `_Generic` keyword in my macro not working?

Probably I'm doing some very basic thing wrong here, but I just cannot figure out what that could be. I can explain my code snippet, but I think it is pretty obvious what I'm trying to do here: create a type-generic macro overload "print function" for my DynamicArray's dynarr_printf method. The question is: why isn't it working?
Thanks in advance!
ENV:
// Mac OS X 10.9.2
// Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
cc -Wall -v -g -std=c11 -I/usr/local/include -c -o build/tmp/main.o main.c
CODE:
void
__dynarr_printf(DynamicArray *dynarr,
void (*print_func)(int, void*));
#define __line_fmt__(fmt) " [%d] " fmt "\n"
static inline void
__dynarr_printf_i(int i, int *v)
{
printf(__line_fmt__("%d"), i, *v);
}
// tons of type specific functions ...
static inline void
__dynarr_printf_def(int i, void *v)
{
printf(__line_fmt__("ptr(%p)"), i, v);
}
#define __dynarr_typef(type) _Generic((type), int: __dynarr_printf_i, \
// tons of type specific funcs ...
default: __dynarr_printf_def)
#define dynarr_printf(dynarr, type) \
(__dynarr_printf(dynarr, __dynarr_typef(type)))
OUTPUT:
main.c:102:5: error: expected expression
dynarr_printf(dynarr, float);
^
./dynarr.h:168:31: note: expanded from macro 'dynarr_printf'
(__dynarr_printf(dynarr, __dynarr_typef(type)))
^
./dynarr.h:157:45: note: expanded from macro '__dynarr_typef'
#define __dynarr_typef(type) _Generic((type), int: __dynarr_printf_i, \
^
1 error generated.
The syntax of a generic selection is:
_Generic ( assignment-expression , generic-assoc-list )
(For the definition of a generic-assoc-list and more information about generic selections, see N1570 section 6.5.1.1.)
The first "operand" is an expression, not a type name. It selects on the type of that expression.
If the type is always scalar, you could change
_Generic((type), ...)
to
_Generic((type)0), ...)

C program syntax "({statement;});" is reported as error by keil

I am trying to define a macro in the format
#define SUM(x,y) ({log_var = x; log_var += y;})
void main(void)
{
unsigned int log_var;
SUM(10,20);
}
Compilation of the same by ARMCC throws an error "Expected an expression" but compilation with GCC doesn't throw the error.
Is it the syntax ({<statements>}); is not allowed in ARMCC or is there any other reason for the same ?
The same disappears when the parentheses is removed. i.e {<statements>}
If you want to have a multi-statement macro body, the usual way is to have a one-iteration do while loop:
#define SUM(x,y) do {log_var = x; log_var += y;} while (0)

liboss static declaration of ‘ioctl’ follows non-static declaration

I'm trying to compile a program that includes liboss's file, but when I compile I get the following error.
In file included from test.c:1:
/opt/local/include/liboss/soundcard.h:342: error: static declaration of ‘ioctl’ follows non-static declaration
/usr/include/sys/ioctl.h:97: error: previous declaration of ‘ioctl’ was here
/opt/local/include/liboss/soundcard.h:353: error: static declaration of ‘open’ follows non-static declaration
/usr/include/sys/fcntl.h:464: error: previous declaration of ‘open’ was here
/opt/local/include/liboss/soundcard.h:363: error: static declaration of ‘close’ follows non-static declaration
/usr/include/unistd.h:476: error: previous declaration of ‘close’ was here
/opt/local/include/liboss/soundcard.h:366: error: conflicting types for ‘write’
/usr/include/unistd.h:535: error: previous declaration of ‘write’ was here
The line where the first error occurs is this one.
# soundcard.h
static inline int LIBOSS_IOCTL (int x, unsigned long y,...)
{
int result;
va_list l;
va_start(l,y);
result = liboss_ioctl(x,y,l);
va_end (l);
return result;
}
# ioctl.h
__BEGIN_DECLS
int ioctl(int, unsigned long, ...);
__END_DECLS
Is there any way in which I can monkey-patch soundcard.h so that this won't be an issue?
Thnx! A.
Specs: Mac OSX 10.7.4, gcc i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1
It sounds like liboss is trying to provide an oss-compatible soundcard interface on a system where that's non-native by redefining the ioctl function to provide the OSS ioctl operations without the kernel having support for them. If this is the case, you need to make sure sys/ioctl.h (or any header that might include it) does not get included in the same source files that use soundcard.h.
Just add static to /usr/include/sys/ioctl.h:97, /usr/include/sys/fcntl.h:464, /usr/include/unistd.h:476 and /usr/include/unistd.h:535 (and undo those changes again after compilation).
In /opt/local/include/liboss/soundcard.h:366 replace int by ssize_t.
# add static
sudo nano +97 /usr/include/sys/ioctl.h
- int ioctl(int, unsigned long, ...);
+ static int ioctl(int, unsigned long, ...);
# replace int by ssize_t
sudo nano +366 /opt/local/include/liboss/soundcard.h
- static inline int LIBOSS_WRITE (int x, const void *y, size_t l)
+ static inline ssize_t LIBOSS_WRITE (int x, const void *y, size_t l)

No warning or error indication when variable defined as static but declared as extern

I came across some code today that surprised me. A variable was defined (outside of a function) in the .c file as being static. However, in the .h file it was declared as being extern. Here is a similar example of the code:
Structure definitions and declaration in .h:
typedef struct
{
unsigned char counter;
unsigned char some_num;
} One_Struct;
typedef struct
{
unsigned char counter;
unsigned char some_num;
const unsigned char * p_something;
} Another_Struct;
typedef struct
{
One_Struct * const p_one_struct;
Another_Struct * const p_another_struct;
} One_Useful_Struct;
extern One_Useful_Struct * const p_my_useful_struct[];
Definition and initialization in .c:
static One_Useful_Struct * const p_my_useful_struct[MAX_USEFUL_STRUCTS] =
{
&p_my_useful_struct_regarding_x,
&p_my_useful_struct_regarding_y,
};
Question:
So my question is, why didn't I receive a compiler error or warning?
The code has been successfully running in other projects for some time now. I did note that the pointer is never used outside of the .c file in which it is defined and was properly defined as static (I removed the external declaration). The only reason that I found it was because I ran Lint on the project and Lint picked it up.
It's certianly not standard C. GCC and clang both detect and give an error on this case:
$ gcc example.c
example.c:4: error: static declaration of ‘x’ follows non-static declaration
example.c:3: error: previous declaration of ‘x’ was here
$ clang example.c
example.c:4:12: error: static declaration of 'x' follows non-static declaration
static int x;
^
example.c:3:12: note: previous definition is here
extern int x;
^
1 error generated.
You must be using a pretty permissive compiler - maybe Visual Studio? I just checked on my Windows machine and VS2003 accepts my example program silently. Adding /Wall does give a warning:
> cl /nologo /Wall example.c
example.c
example.c(4) : warning C4211: nonstandard extension used : redefined extern to static
Looks to me like you're using an extension of whatever compiler it is that you're using.

Resources