Pelles C forum
C language => Expert questions => Topic started by: japheth on June 16, 2009, 10:34:09 PM
-
Hello,
I tried to compile JWasm with PellesC. Almost everything compiles without errors, with one exception. The issue is the initialization of a structure which contains 2 bitfields and a character array of "unknown" size:
#include <stdio.h>
typedef unsigned int uint_32;
typedef unsigned char uint_8;
typedef struct line_item {
struct line_item *next;
uint_32 lineno:20, srcfile:12;
uint_32 list_pos; /* position .LST file */
uint_8 macrolevel; /* just a bit (macrolevel > 0?) is needed */
char line[];
} line_item;
line_item endl = { NULL, 0, 0, 0, 0, "END" };
pocc complains:
main3.c(15): warning #2213: Multiple initializers for the same element (at offset 13).
main3.c(15): error #2139: Too many initializers.
while MSVC, OW and gcc don't see a problem.
How is this supposed to be defined in Pelles C ?
-
I would guess that
uint_32 lineno:20, srcfile:12;
is not being parsed as expected
Does
uint_32 lineno:20;
uint_32 srcfile:12;
compile with Pelle's C without warning or error?
Robert Wishlaw
-
I have tried something with your code. I my opion the error message are not related to the bitfields (when you remove the bitfield size you get the same error message). The problem seem to be the empty char array. If you use an empty string instead of "END" it compiles.
But at the moment I have no good solution for you. Is it possible to use a pointer to the char array?
-
But at the moment I have no good solution for you. Is it possible to use a pointer to the char array?
No, that's not an option. There's a workaround, of course, but since the item's size is actually defined by the length of the <line> member, it's rather ugly and needs dynamic allocation:
#ifdef __POCC__
line_item *endl = AsmAlloc( sizeof( line_item ) + 4 );
endl->next = NULL;
endl->srcfile = 0;
endl->lineno = LineNumber;
endl->list_pos = 0;
strcpy( endl->line, "END");
LineStoreHead = endl;
#else
endl.lineno = LineNumber;
LineStoreHead = &endl;
#endif
-
Can't you declare the string var to have the right size?
typedef struct line_item {
struct line_item *next;
uint_32 lineno:20, srcfile:12;
uint_32 list_pos; /* position .LST file */
uint_8 macrolevel; /* just a bit (macrolevel > 0?) is needed */
char line[4];
} line_item;
John
-
Can't you declare the string var to have the right size?
No, it's variable. The sample which I posted is a test case only.
-
No, it's variable. The sample which I posted is a test case only.
I think this is also no good solution for your example?
char line[] = {"\0\0\0\0\0\0\0\0\0\0\0\0\0END"};
line_item *uendl = (line_item *)line;
:)
-
Can't you declare the string var to have the right size?
No, it's variable. The sample which I posted is a test case only.
From the original code.
void StoreLine( char * string )
{
int i;
i = strlen(string) + 1;
LineStoreCurr = AsmAlloc( i + sizeof(line_item) );
LineStoreCurr->next = NULL;
LineStoreCurr->lineno = LineNumber;
LineStoreCurr->list_pos = list_pos;
LineStoreCurr->macrolevel = MacroLevel;
memcpy( LineStoreCurr->line, string, i );
LineStoreTail->next = LineStoreCurr;
LineStoreTail = LineStoreCurr;
}
Even the original has to allocate for a string of unknown length. The most elegant way would be to make a func that deals with this issue.
EDIT: Here's a page on 'flexible array members' which is what you are using.
http://books.google.co.uk/books?id=iRa-3L4jLhEC&pg=PA554&lpg=PA554&dq=flexible+array+member&source=bl&ots=dXiybr7a3K&sig=1BM5U1NosUCz_5w1YZpG80G9Xd0&hl=en&ei=Yk46So7-NJm6jAe_zvimDQ&sa=X&oi=book_result&ct=result&resnum=7 (http://books.google.co.uk/books?id=iRa-3L4jLhEC&pg=PA554&lpg=PA554&dq=flexible+array+member&source=bl&ots=dXiybr7a3K&sig=1BM5U1NosUCz_5w1YZpG80G9Xd0&hl=en&ei=Yk46So7-NJm6jAe_zvimDQ&sa=X&oi=book_result&ct=result&resnum=7)
John
-
Hi,
no time to test but this should really work ;-)
#include <stdio.h>
typedef unsigned int uint_32;
typedef unsigned char uint_8;
typedef struct line_item {
struct line_item *next;
uint_32 lineno:20, srcfile:12;
uint_32 list_pos; /* position .LST file */
uint_8 macrolevel; /* just a bit (macrolevel > 0?) is needed */
char *line;
} line_item;
line_item endl = { NULL, 0, 0, 0, 0, "END" };
Greetings
Seltsamuel
-
no time to test but this should really work ;-)
#include <stdio.h>
typedef unsigned int uint_32;
typedef unsigned char uint_8;
typedef struct line_item {
struct line_item *next;
uint_32 lineno:20, srcfile:12;
uint_32 list_pos; /* position .LST file */
uint_8 macrolevel; /* just a bit (macrolevel > 0?) is needed */
char *line;
} line_item;
line_item endl = { NULL, 0, 0, 0, 0, "END" };
I think also this is a good solution, but japheth don't like it. :(
So I would prefer a constructor like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned int uint_32;
typedef unsigned char uint_8;
typedef struct line_item {
struct line_item *next;
uint_32 lineno:20, srcfile:12;
uint_32 list_pos; /* position .LST file */
uint_8 macrolevel; /* just a bit (macrolevel > 0?) is needed */
char line[];
} line_item;
line_item *endl;
line_item *create_line_item(line_item *next, uint_32 srcfile, uint_32 lineno, uint_32 list_pos, uint_8 macrolevel, char * string )
{
line_item *litem = (line_item *)malloc( sizeof( line_item ) + strlen(string) + 1 );
litem->next = next;
litem->srcfile = srcfile;
litem->lineno = lineno;
litem->list_pos = list_pos;
litem->macrolevel = macrolevel;
strcpy( litem ->line, string);
return litem;
}
void destroy_line_item(line_item *li)
{
if (li != NULL)
{
free(li);
}
}
int main(int argc, char *argv[])
{
endl = create_line_item( NULL, 0, 0, 0, 0, "END" );
printf("%s\n", endl->line);
destroy_line_item(endl);
return 0;
}
Alex ;)
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
typedef struct line_item
{
struct line_item * next;
uint32_t lineno :20;
uint32_t srcfile :12;
uint32_t list_pos; /* position .LST file */
uint8_t macrolevel; /* just a bit (macrolevel > 0?) is needed */
char line[];
}
line_item;
static line_item *create_line_item(line_item const * item, char const * line)
{
size_t line_size = strlen(line) + 1;
line_item * litem = malloc(line_size + sizeof *litem);
if(litem != NULL)
{
*litem = *item;
memcpy(litem->line, line, line_size);
}
return litem;
}
static inline void destroy_line_item(line_item * item)
{
free(item);
}
int main(void)
{
line_item * endl = create_line_item(&(line_item){NULL, 0, 0, 0, 0}, "END");
puts(endl->line);
destroy_line_item(endl), endl = NULL;
return 0;
}
-
The last member (line) is what the C standard calls a "flexible array member" - this was added in C99. AFAIK, initialization of a structure with a flexible member stops just before such a member - the error is correct (and the warning is just noice). Before C99, this was an extension in several C compilers which may or may not agree on the behaviour...