X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f From: "Rod Pemberton" Newsgroups: comp.os.msdos.djgpp Subject: Re: Upgrading from a bad C compiler Date: Fri, 20 Jul 2012 19:20:19 -0400 Organization: Aioe.org NNTP Server Lines: 189 Message-ID: References: <17d4b525-2c31-4c20-b3c5-a7118343e9a5 AT googlegroups DOT com> NNTP-Posting-Host: CNsg4fVcCsvs3UaOgZtQCw.user.speranza.aioe.org X-Complaints-To: abuse AT aioe DOT org X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.2001 X-Notice: Filtered by postfilter v. 0.8.2 X-Newsreader: Microsoft Outlook Express 6.00.2800.2001 X-Priority: 3 X-MSMail-Priority: Normal Bytes: 6402 To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Reply-To: djgpp AT delorie DOT com "K.J.Williams" wrote in message news:17d4b525-2c31-4c20-b3c5-a7118343e9a5 AT googlegroups DOT com... > > I recently upgraded, and imported some source code from a > non-standard ANSI C compliant compiler (Borland Turbo > C++ 3.0 for DOS) to DJGPP because of the memory limitation > and the fact that TC++ far invention for accessing memory does > not work. Now I am using DJGPP via RHIDE get over this > disadvantage of memory, and I am running into a lot of compiler > (syntax) errors because the old compiler I used was not compliant. > The only difference between RHIDE and Turbo C++ that I have > noticed, is that there is no verbose explanation of the errors - > which I could access in TC++. Is there a documentation where > I can find out more in depth what these errors mean? ... > 3 examples of errors - simplified (2 of which I solved)- things > that I could do in C in TC++ that DJGPP compiler nails me on : Ok. > #1 > > //in myfile1.c > > short int myfunc(char x) > { > char w[0] = x; > // legal in TC++ - but illegal in DJGPP, to assign the address > // of x to w[0] in this manner > .... > .... > return 0; > } > It's \\ not // for C++ comments... That assigns the char x to the first char in the array of char's w. That's legal C. > the fix: > > char w[0] = &x; > Taking the address of x is one way to get the address of x. Assigning an address, which is not a 'char' but 'char *', into a char array likely has side effects, i.e., the address is probably much larger in size than a char. At a minimum, you should've been warned by the compiler about a missing cast, or an invalid pointer to integer conversion. Try, gcc -Wall -pedantic Or, gcc -Wall -ansi -pedantic I.e., to produce legal C, you should have to cast '&x' to 'char', e.g., char w[0]=(char)&x; The cast _should_ reduce the size of the address you're storing, i.e., from a pointer to char. If you're saving an address into an array, that's probably not what you want... So, the 'fix' you suggested may do something odd (it should), i.e., truncation of the address' value when stored. It's probably better to do something that won't truncate: *(unsigned long *)w=(unsigned long *)&x; Addresses in ANSI C should be returned as 'void *' (instead of 'char *' for K&R C). 'void *' can do "lossless" pointer conversions in ANSI C, but you can't dereference 'void *' types. They don't point to a type. That's what 'void' means. They're just an address - without an object. But, you can cast 'void *' through intermediate integers if they are large enough in size, then dereference to store, which is what the example does. Alternately, you could use a union. This would eliminate the need for casts. Casts are generally abhorred and not recommended for novices. union { char w[4]; void *address; } layout; layout.address=&x; putc(w[0]); printf("%c",w[1]); ... Another solution could be, depending on the program, to declare x as a 'char *' instead of 'char' and pass in the address to the procedure. > #2 > > #define WIDGETS 200 > > //in myfile2.c - a global struct > > struct mystuff > { > .... > .... > }; > > struct mystuff *mything = NULL; //for use with malloc() & free() > > short int badstuff = 0; > > short int myfunc(void) > { > short unsigned int x; > .... > x = sizeof(mystuff)*WIDGETS; //legal in TC++ but illegal in DJGPP > .... > return 0; > } > > > the fix: > > x = sizeof(mything)*WIDGETS; // I don't understand why "mystuff" > > //doesn't work instead of using mything... > You either 1) have 'mystuff' in the incorrect location, or you 2) need 'struct' in the sizeof(). E.g., struct new_type { ... } variable_of_new_type ; 'new_type' declares a new struct type. 'variable_of_new_type' allocates a variable of the new struct type. To reference 'new_type', you need to always use 'struct' as in 'struct new_type'. It's not a variable. It's just a type. I.e., good for sizeof() or self-referenced struct. To use 'variable_of_new_type', you need to use 'variable_of_new_type'. It's a variable which allocated with the type of the struct. You can store values to variables. So, you've placed 'mystuff' where 'new_type' is. That just declares a new type of struct. That needs the keyword 'struct' as in 'struct mystuff'. I'd guess that 'mystuff' should've been a variable. I.e., 'mystuff' should be where 'variable_of_new_type' is. You can use a comma to add additional variables where 'variable_of_new_type' is, and/or you can declare them separately from the struct: struct new_type { ... } ; ... ... struct new_type var1, var2; Usage of struct and union types (not variables) need the 'struct' or 'union' keyword, respectively. Typedef's don't. There is no usage keyword for typedef's. I.e., they are "implicit". It's one of the errors of C's grammar. It breaks LALR(1). Typedef's were introduced to C (1977). The missing usage keyword for typedef's introduced a parsing conflict with implicit int's (1974). ANSI C (C89) changed the scoping rules in an attempt to eliminate the problem. That solution didn't work for all cases. That led to the elimination of implicit int's in ISO C (C99). > #3 > > //in myfile3.c , declares two extern of two variables in myfile2.c > outside before any function //bodies > [...] Sorry, I'm no help with this one. Rod Pemberton