Path: csiph.com!usenet.pasdenom.info!aioe.org!.POSTED!not-for-mail From: "Rod Pemberton" Newsgroups: comp.lang.misc Subject: Re: A good subset of C Date: Tue, 06 May 2014 06:48:05 -0400 Organization: Aioe.org NNTP Server Lines: 162 Message-ID: References: NNTP-Posting-Host: CNsg4fVcCsvs3UaOgZtQCw.user.speranza.aioe.org Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit X-Complaints-To: abuse@aioe.org User-Agent: Opera Mail/12.16 (Linux) X-Notice: Filtered by postfilter v. 0.8.2 Xref: csiph.com comp.lang.misc:2207 On Mon, 05 May 2014 19:42:51 -0400, James Harris wrote: > "Rod Pemberton" wrote in message > news:op.xfer8g1j6zenlw@localhost... >> On Mon, 05 May 2014 15:59:26 -0400, James Harris >> wrote: >>> * Structs >> >> Yes. >> >> No typedefs? They don't allocate space. I.e., good for overlaying >> data structures onto "arrays" of char, e.g., databases, records, >> filesystems, struct nodes in a linked list, etc. > > Don't forget a typedef is just an alias for something that already > exists. > No, it's not for something that already exists. Something must be declared for it to "exist" as an object in C. A typedef provides a reference to a object type, which may be allocated or unallocated. It acts as a language element, a new type, an extension of C. The typedef itself never exists as an object. I.e., it has no storage for data. When used by itself, it provides naming and addressing. When used in a declaration, it will provide naming, addressing, and allocation for the object defined in the declaration according to the object used to define the typedef. 1) first example /* The structA structure has been declared as a struct here */ /* The structA structure has space allocated for it here */ /* The layout of structA is defined here */ /* There is no typedef here */ struct structA { char c; int d; }; /* Now structures structB and structC have been declared */ /* Both structB and structC have structA's layout */ /* Both structB and structC have space allocated for them */ struct structA structB, structC; /* This is a pointer to a struct of structA's layout */ /* The pointer hasn't been set to point to anything */ /* A struct has been allocated above to which it can be set */ struct structA *tptr1; 2) second example /* No structure has been declared here */ /* No structure has space allocated for it here */ /* The typedef represents the struct layout */ /* No space is allocated for the typedef */ /* tdef is the name of the typedef */ typedef struct { char c; int d; } tdef; /* Now structures struct1 and struct2 have been declared by typedef */ /* Both struct1 and struct2 have space allocated for them */ /* Both struct1 and struct2 have the struct layout of the typedef'd struct: tdef */ tdef struct1, struct2; /* This is a pointer to a struct of the typedef'd struct's layout */ /* The pointer hasn't been set to point to anything */ /* No struct has been allocated for which the pointer can point to */ /* The space for the pointer to point to is allocated via some other method */ tdef *tptr2; 3) third example - you can combine them ... /* structA has space allocated. tdef1 and tdef2 do not. */ /* one struct can be defined, but multiple typedefs ... */ typedef struct structA { char c; int d; } tdef1, tdef2; struct structA structB, structC; /* space is allocated for structs */ struct structA *tptr1; /* pointer to struct with structA's layout */ tdef1 struct1, struct2; /* space is allocated for structs*/ tdef2 *tptr2; /* pointer to struct with structA's layout */ Isn't that lovely? :-) In the third example, you could say that tdef1 and tdef2 represent the syntax 'struct structA', but you can't say that about the second example since the struct is unnamed and C doesn't support unnamed objects (or didn't, C99 might ...). > Consider > > struct Tag { ... }; > > No typedef but, here, the struct needs no space allocation. > It is just a definition and Tag is just a name. > Does the '...' represent C's ellipsis or stuff you didn't want to type out? Was this a struct prototype or an incomplete struct definition? Once an incomplete struct definition is completed, or a full structure is defined. Space is allocated for that struct. >>> * Choice of where to place variables: stack, block, module >> >> Why? >> >> (That kind of defeats the purpose of C. Use Forth for that.) > > Consider > > int a; > void fn() { > int b; > static int c; > for (int d;;) { > } > for (int e;;) { > } > } > > Here the intention is that A has module scope and storage, B has stack > storage, C has module storage but function scope, and D has block scope > and > probably some form of stack storage but would not have to compete with > E. D > and E could occupy the same stack space. Yes, but except for "A [with] module scope", nowhere do I, nor you, need to know that. It's convenient to know that "B has stack storage" (typically). In all cases, the compiler can relocate the storage from memory, to register, to stack, vice-versa, either-or, whatever, and back, space permitting, i.e., no structs will fit in a register. I.e., while these have a typical way they're implemented in C, the compiler can optimize or change that as needed. Not dealing with this issue directly allows the compiler to do the "best thing". Specifically, the fact C can generate code for a variable no matter where it's stored or moved is one of the better ideas behind C, IMO. Compare with Forth, where you can't do anything (almost nothing) to their variables. Forth doesn't have any (only one) defined operation which works on variables. They could easily, but don't. To do things the "Forth way", you must move them to the stack, manipulate the value on the stack, perhaps with other values on the stack at the same time, juggle them a bit, then store the decide result back into the variable. All of that is done manually, by the programmer... Rod Pemberton