delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2012/07/20/19:30:16

X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f
From: "Rod Pemberton" <do_not_have AT notemailnot DOT cmm>
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: <jucp01$p35$1@speranza.aioe.org>
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" <lordwilliams1972 AT gmail DOT com> 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




- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019