How do you initialize your complex structs in C?
I mean, something like 'struct foo {short bar[2]; int baz}'?
There exist 2 styles:
struct foo x = {1, 2, 3} (flat list)
struct foo x = {{1, 2}, 3} (nested braces)
It seems gcc prefers the latter. The former initializer style triggers
'warning: missing braces around initializer' when '-Wall'
or '-Wmissing-braces' switch is present.
Of course, it's better to always provide structured initializer
instead of flat one for complex structs, but sometimes this is
not possible, because you need to use system-provided initializers
like e.g. PTHREAD_MUTEX_INITIALIZER and the
initializer nesting style they conform to is not known and/or is
out of your control. Then, if you use '-Wall -Werror'
pair of switches like guile-1.8.7 does, you've got a problem
here.
The guile's smart-ass ./configure script works
with '-Wall -Werror' switches and checks
'whether PTHREAD_MUTEX_INITIALIZER needs braces...'
On HP-UX this check produces 'yes' because:
PTHREAD_MUTEX_INITIALIZER is flat list:
'{0x36, 0, 0x81, 1, 1, 1, 1, 1LL, 1, 0, 0, 0, -1, 0, ...}'
pthread_mutex_t is complex struct, like
'{short __m_short[2]; int __m_int; ...}'
- '
-Wall -Werror' are in effect
- gcc wants initializer with nested braces for the
pthread_mutex_t, but gets flat list
- gcc dies with 'warning: missing braces around __m_short initializer'
What happens next is very funny: guile places additional
pair of braces around PTHREAD_MUTEX_INITIALIZER
which results in {{0x36, 0, 0x81, 1, 1, 1, 1, 1LL, 1, 0, 0, 0, -1, 0 ...}}
initializer. During compilation this initializer is attempted
at pthread_mutex_t variable which triggers
'warning: excess elements in array initializer
(near initialization for `async_mutex.__m_short')' and
build fails. Here's why:
0x36 goes to .__m_short[0]
0 goes to .__m_short[1]
0x81 wants to go into the .__m_short
array too, but there's no more space in that array left
- all other elements of initializer are also tried to
be assigned to the
.__m_short and
do not fit (warning is repeat several times).
Here you see that ./configure effectively
has broken the code completely, because
'excess elements' warning is much more
serious than 'missing braces'. I think
it's safe to assume that all those excess elements
are essential non-default values for struct members that
weren't put into correct places but discarded instead. Some
important members didn't receive their values. For example,
0x81 wasn't put into __m_int
and so on.
P.S. pthread_mutex_t
and PTHREAD_MUTEX_INITIALIZER are defined this way
on HP-UX 11.31 is64:
# ifdef __LP64__
# define __MPOINTER void *__m_ptr
# define __POINTER_SET ((void *) 1LL)
# else
# define __MPOINTER int __m_pad; \
void *__m_ptr
# define __POINTER_SET 0, ((void *) 1L)
# endif
struct __pthread_mutex {
short __m_short[2];
int __m_int;
int __m_int1[4];
__MPOINTER;
int __m_int2[2];
int __m_int3[4];
short __m_short2[2];
int __m_int4[5];
int __m_int5[2];
};
typedef struct __pthread_mutex pthread_mutex_t;
#define __SPNLCK_INITIALIZER \
1, 1, 1, 1, \
__POINTER_SET, \
1, \
0
#define PTHREAD_MUTEX_INITIALIZER { \
__PTHREAD_MUTEX_VALID, 0, \
(PTHREAD_MUTEX_DEFAULT | PTHREAD_PROCESS_PRIVATE), \
__SPNLCK_INITIALIZER, \
0, 0, -1, 0, \
0, __LWP_MTX_VALID, 0, 1, 1, 1, 1, \
0, 0 \
}
|