phil@uxg.cso.uiuc.edu (12/21/88)
I want to write a subroutine in C, called S. I want S to be known outside. I also want to have two subroutines X and Y to be known ONLY to S (not known outside of S). Either can be called by S, and each calls the other in a recursive way. I also need to share several variables entirely within this context (shared between S, X, Y). They can be static. There will only be 1 instance of S (and therefore also of X and Y, but that should be hidden). Main program M should be able to call S, but any references to X and Y will not be resolved by the module S. How do I lay out the arrangement of source for S? An example would be appreciated. Thanks. --Phil--
burgett@adobe.com (Michael Burgett) (12/22/88)
In article <2800002@uxg.cso.uiuc.edu> phil@uxg.cso.uiuc.edu writes: [ description of needed module deleted ] >How do I lay out the arrangement of source for S? An example would be >appreciated. Thanks. in a file, say S.c: static int foo, bar; /* foo and bar are accessable by all functions in this file but are not visible outside it. */ int S() /* S() will be available as a public symbol */ { ... } static int f1() /* can be referenced by S() or f2() but is not { visible outside this file */ ... } static int f2() /* can be referenced by S() or f1() but is not { visible outside this file */ ... } should do what you are asking for... ---------------------------------- mike burgett burgett@adobe.com "squid and red bean stew served daily...."
gpasq@picuxa.UUCP (Greg Pasquariello X1190) (12/22/88)
In article <2800002@uxg.cso.uiuc.edu> phil@uxg.cso.uiuc.edu writes: - -I want to write a subroutine in C, called S. I want S to be known outside. -I also want to have two subroutines X and Y to be known ONLY to S (not known -outside of S). Either can be called by S, and each calls the other in a -recursive way. I also need to share several variables entirely within -this context (shared between S, X, Y). They can be static. There will -only be 1 instance of S (and therefore also of X and Y, but that should -be hidden). Main program M should be able to call S, but any references -to X and Y will not be resolved by the module S. - -How do I lay out the arrangement of source for S? An example would be -appreciated. Thanks. - ---Phil-- Here's how to do it. This is in the source file S.c, and assumes that the routines return ints. Just change your code accordingly if they don't. It also does not show any function parameters, so you will have to customize your code for that also (obviously). /* This declares your functions and variables as static (i.e. known only within this source module). See K+R2 A4.1. */ static int X(); static int Y(); static int var1; static int var2; /* This declaration of S() will enable it to be found externally when called by any other routine in the program, for example M(). Notice that S has access to the both the static variables and the static functions X() and Y(). */ S() { var1 = 1; X(); Y(); ... } /* Here, your two static functions X() and Y() have access to the variables, as well as each other. */ static int X() { var1 = var2 = 0; Y(); ... } static int Y() { var1 = var2 = 0; X(); ... } -- ============================================================================= By the time they had diminished from Greg Pasquariello AT&T PMTC 50 to 8, the dwarves began to suspect Hungry. att!picuxa!gpasq =============================================================================
evil@arcturus.UUCP (Wade Guthrie) (12/23/88)
In article <2800002@uxg.cso.uiuc.edu>, phil@uxg.cso.uiuc.edu writes: > I want to write a subroutine in C, called S. I want S to be known outside. > I also want to have two subroutines X and Y to be known ONLY to S (not known > outside of S). Either can be called by S, and each calls the other in a > recursive way. I also need to share several variables entirely within > this context (shared between S, X, Y). They can be static. There will > only be 1 instance of S (and therefore also of X and Y, but that should > be hidden). Main program M should be able to call S, but any references > to X and Y will not be resolved by the module S. > In a file, which is separately compiled before being linked to the rest of your code, put S(), X(), and Y(). Declare X() and Y() to be static which, in addition to causing variables to maintain their values between calls, causes symbols to be unknown outside that file. As an example: ----- file foo.c ------------- #include <stdio.h> main() { global(); local(); } ----- file bar.c ------------- #include <stdio.h> int global() { puts("entered global"); local(); puts("leaving global"); } static int local() { puts(" calling local"); } -------------------------- try compiling it, and you'll see that main cannot access local. It works if you either 1) remove the call to local in main, or 2) remove the static declaration of local. Wade Guthrie Rockwell International Anaheim, CA (Rockwell doesn't necessarily believe / stand by what I'm saying; how could they when *I* don't even know what I'm talking about???)
frank@rsoft.UUCP (Frank I. Reiter) (12/23/88)
In article <2800002@uxg.cso.uiuc.edu> phil@uxg.cso.uiuc.edu writes: > > I want S to be known outside. >I also want to have two subroutines X and Y to be known ONLY to S (not known >outside of S). Either can be called by S, and each calls the other in a >recursive way. I also need to share several variables entirely within >this context (shared between S, X, Y). They can be static. Put S(), X(), and Y() in their own file. Declare X() and Y() to be static and do the same with any global variables to be accessed only by S(), X(), and Y(). Other modules will be able to call S() but not X() or Y() or any of the static variables. -- *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* Frank I. Reiter \ / UUCP: {uunet,ubc-cs}!van-bc!rsoft!frank Langley, British Columbia / \ BBS: Mind Link @ (604)533-2312 *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
eric@snark.UUCP (Eric S. Raymond) (12/23/88)
In article <2800002@uxg.cso.uiuc.edu>, phil@uxg.cso.uiuc.edu writes: > I want to write a subroutine in C, called S. I want S to be known outside. > I also want to have two subroutines X and Y to be known ONLY to S (not known > outside of S). Either can be called by S, and each calls the other in a > recursive way. I also need to share several variables entirely within > this context (shared between S, X, Y). They can be static. There will > only be 1 instance of S (and therefore also of X and Y, but that should > be hidden). Main program M should be able to call S, but any references > to X and Y will not be resolved by the module S. > > How do I lay out the arrangement of source for S? An example would be > appreciated. Thanks. Let xreturn, yreturn and sreturn be the return types of X, Y and S. Then the simplest way to accomplish this is: static int sharevar1; static char *sharevar2; static xreturn X() { yreturn Y(); /* this is the trick; forward-declare Y() */ /* text of X */ } static yreturn Y() { /* text of Y */ } sreturn S() { /* text of S */ } You might want to put S() up front and forward-declare X() and Y(). That would look like: sreturn S() { xreturn X(); yreturn Y(); /* text of S */ } I use a #define forward /*empty*/ so I can write: sreturn S() { forward xreturn X(); forward yreturn Y(); /* text of S */ } Be aware that there is some theological variation among C compilers on whether forwards in functions remain in effect for only function scope until the end of the module file. ANSI C, I believe, assumes the former, and writing as if the former were true does no harm on compilers that assume the latter. I gather you're a novice. Congratulations on having learned concern for scope and visibility issues early. Too many people never break the bad habit C encourages of leaving their functions and data promiscuously exposed. -- Eric S. Raymond (the mad mastermind of TMN-Netnews) Email: eric@snark.uu.net CompuServe: [72037,2306] Post: 22 S. Warren Avenue, Malvern, PA 19355 Phone: (215)-296-5718
djones@megatest.UUCP (Dave Jones) (12/28/88)
From article <eWZhv#4VSvya=eric@snark.UUCP>, by eric@snark.UUCP (Eric S. Raymond): > > I use a #define forward /*empty*/ so I can write: > I am starting a definitive (ahem) collection of SLMs. This has the distinction of being the first.
eric@snark.UUCP (Eric S. Raymond) (12/29/88)
In <1130@goofy.megatest.uucp>, djones@megatest.UUCP (Dave Jones) writes: > I am starting a definitive (ahem) collection of SLMs. This has the > distinction of being the first. SLM = Silly Little Macro? :-) Here're two more that I use: #define const /*empty*/ /* on non-ANSI compilers */ #define public /*empty*/ This latter goes with #define private static I may drop `forward' though. -- Eric S. Raymond (the mad mastermind of TMN-Netnews) Email: eric@snark.uu.net CompuServe: [72037,2306] Post: 22 S. Warren Avenue, Malvern, PA 19355 Phone: (215)-296-5718
dmg@ssc-vax.UUCP (David Geary) (01/06/89)
Frank Reiter writes: >In article <2800002@uxg.cso.uiuc.edu> phil@uxg.cso.uiuc.edu writes: >> >> I want S to be known outside. >>I also want to have two subroutines X and Y to be known ONLY to S (not known >>outside of S). Either can be called by S, and each calls the other in a >>recursive way. I also need to share several variables entirely within >>this context (shared between S, X, Y). They can be static. >Put S(), X(), and Y() in their own file. Declare X() and Y() to be static >and do the same with any global variables to be accessed only by S(), X(), >and Y(). >Other modules will be able to call S() but not X() or Y() or any of the static >variables. Frank is correct, this is exactly what you want to do. However, I like to do the following: #define PRIVATE static #define PUBLIC Now, we can declare the functions S(), X(), and Y() thusly: PUBLIC int S() { ... } PRIVATE int X() { ... } PRIVATE int Y() { ... } And, of course, we can declare external variables in the same manner: PUBLIC int x,y; PRIVATE float f,g; BTW, these macros are not my invention, I first saw them in a book entitled "Operating Systems Design and Implementation" (I think the title is correct). A very good book BTW, on the MINIX OS. David -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ David Geary, Boeing Aerospace, ~ ~ #define Seattle RAIN ~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ariel@lznh.UUCP (<10000>Ariel Aloni) (01/06/89)
In article <2459@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes: > > Frank is correct, this is exactly what you want to do. However, I like >to do the following: > >#define PRIVATE static >#define PUBLIC > ... Sure, this thing has no end, why not : #define TINY short #define HUGE long #define RECORD struct ..... :-) C is terse and accurate, if you want to invent new keywords for C please don't abuse CPP, design your own new language. In your particular example the change of 'static' is very confusing since 'static' has a different meaning for functions and variables. ariel -- Ariel A. Aloni att!lznh!ariel
bowles@eris.berkeley.edu (Jeff A. Bowles) (01/07/89)
>In article <2459@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes: > > Frank is correct, this is exactly what you want to do. However, I like >to do the following: > >#define PRIVATE static >#define PUBLIC > ... I worked for a very short time for a creepy compiler company that had several hundred thousand lines of this sort of crap. PRIVATE -> static PUBLIC -> "" INT16 -> short int INT32 -> long int and so on. By the time these fools were done, they weren't coding in C, they were coding in their own language - and often it was just because they liked a particular style that the K&R compiler [proper] didn't accept. One person I know used typedef's for every last data type in a fairly large control system. You would see a declaration like THING x; and not know if you could put "&" in front of it (it might be an array) or if it was a integral object or what. Data hiding is one thing, but not if it's incomplete, and not if it serves no purpose. We've all seen (or heard about) the source to the Bourne shell, in which Steve Bourne furnished ALGOL-like #defines and wrote the entire shell in it. (Don't get me wrong, I like Algol W, an older language, more than I do C - in many contexts.) But if you're using the C preprocessor, or things like typedefs, to reformat a program, ask how much you're asking someone to know about your program before you do it. It's one thing to clarify an often-existing sequence of code, e.g. #define REGLOOP(i) for(i = 0; i < REGSZ; ++i) or to hide an implementation within library routines or header files, as in the case of the "-ldbm" or "-lmp" libraries, and another to gratituously add the sort of foolishness the original posting suggests. Some people use: typedef enum {true = 1, false = 0} boolean; and when you're able to use this single line, and later say "if (true)..." I'll probably use this - it DOES make things clearer. I believe that ANSI C will make this sort of thing easier, which is good. Where is the line? Probably the best way to answer is by asking if the statement (e.g. "if (true)..." or "REGLOOP(i) { ... }") would make sense in a fragment. And it's hard to convince me that most pretty-printing would. Jeff Bowles
mlandau@bbn.com (Matt Landau) (01/07/89)
In comp.lang.c (<1987@lznh.UUCP>), ariel@lznh.UUCP (<10000>Ariel Aloni) writes: >>#define PRIVATE static >>#define PUBLIC >C is terse and accurate, if you want to invent new keywords for C >please don't abuse CPP, design your own new language. In general, this is good advice. If you're going to program in C, then program in *C*; don't end up with something like the original /bin/sh code, which no real C programmer ends up wanting to deal with. But . . . >In your particular example the change of 'static' is very confusing >since 'static' has a different meaning for functions and variables. . . . on the other hand, this is precisely why an alias for "static" may be a *good* idea. One can argue that overloading static with two different meanings was a flaw in the original language design -- there does not seem to me to be all that much similarity between persistent variables in a function and variables/functions that are hidden from other source files, so it's not clear why you would want to use the same keyword to describe both. Using something like PRIVATE for file-level static variables or functions, and the traditional static for variables that persist across function invocations, serves to make the distinction clear. -- Matt Landau Waiting for a flash of enlightenment mlandau@bbn.com in all this blood and thunder
nagel@blanche.ics.uci.edu (Mark Nagel) (01/07/89)
In article <1987@lznh.UUCP>, ariel@lznh (<10000>Ariel Aloni) writes: |In article <2459@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes: |> |> Frank is correct, this is exactly what you want to do. However, I like |>to do the following: |> |>#define PRIVATE static |>#define PUBLIC | |C is terse and accurate, if you want to invent new keywords for C |please don't abuse CPP, design your own new language. |In your particular example the change of 'static' is very confusing |since 'static' has a different meaning for functions and variables. Wrong, it makes it more clear. The static keyword is overloaded, so why is it confusing to rename it to more accurately reflect the desired semantics? It is easy to abuse cpp, but this is not such a case. Mark Nagel @ UC Irvine, Dept of Info and Comp Sci ARPA: nagel@ics.uci.edu | The world is coming to an end. UUCP: {sdcsvax,ucbvax}!ucivax!nagel | Please log off.
djones@megatest.UUCP (Dave Jones) (01/07/89)
From article <1987@lznh.UUCP), by ariel@lznh.UUCP (<10000)Ariel Aloni):
) In article <2459@ssc-vax.UUCP) dmg@ssc-vax.UUCP (David Geary) writes:
))
)) Frank is correct, this is exactly what you want to do. However, I like
))to do the following:
))
))#define PRIVATE static
))#define PUBLIC
)) ...
) Sure, this thing has no end, why not :
)
) #define TINY short
) #define HUGE long
) #define RECORD struct
) ..... :-)
)
Point of order.
Would it be acceptable for me to install these last three
in my SLM database, even though they are conspicously smileyed?
I missed the last USNIX Symposium on Ethics in Net.sarcasm.
djones@megatest.UUCP (Dave Jones) (01/07/89)
From article <18789@agate.BERKELEY.EDU>, by bowles@eris.berkeley.edu (Jeff A. Bowles): > Some people use: > typedef enum {true = 1, false = 0} boolean; > and when you're able to use this single line, and later say "if (true)..." > I'll probably use this - it DOES make things clearer. I can't agree. I know of one _extremely_ large project where several programmers have defined "YES" and "NO" and "TRUE" and "FLASE". So you get "redefined" messages if you need to include header files from two different packages. To make things worse, one programmer who was unfamiliar with C conventions defined "YES" as 0 and "NO" as 1. Gack. His header files will break all the other ones. That sort of proves that an SLM was out of place: It has to mean what it means. If you change the #define, you change the logic and break the program. I've noticed that some released Sun software gets "redefined" messages. In one header file there is something like this: #define true (0==0) and in another #define true (0!=1) or something like that. Pooh.
gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/07/89)
In article <2459@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes: >#define PRIVATE static >PRIVATE int X() { ... } The only legitimate reason for doing this is to make it convenient to force these functions to have external linkage when using a debugger that doesn't provide decent support for static functions. >#define PUBLIC This one is a waste of time.
evil@arcturus.UUCP (Wade Guthrie) (01/10/89)
In article <18789@agate.BERKELEY.EDU>, bowles@eris.berkeley.edu (Jeff A. Bowles) writes: > I worked for a very short time for a creepy compiler company that had > several hundred thousand lines of this sort of crap. > > PRIVATE -> static > PUBLIC -> "" > INT16 -> short int > INT32 -> long int In general I agree that typedefs and macros should be used judiciously in order to help make things readable to the ordinary C programmer (if you can call *any* C programmer ordinary :-> ). However, I have seen the use for INT16 and INT32 -- portability where the precision is absolutely important. For example: you want to partition a circle into little angles, and you want to flag an occurrence of something if it exists in each angle. The way I chose to implement this was to partition my circle into 32 sections (the number of bytes in the long or int on my machine -- to take advantage of the speed improvements on some operations, I chose to use int) and do bitwise operations to set and check flags represented by the bits in that int. Now, I need to port this to a machine that has 16 bit ints -- portability falls on its face. This can be circumvented by using INT32 where the size is important (and using short, int, and long where it is not so critical). Wade Guthrie evil@arcturus.UUCP Rockwell International Anaheim, CA (Rockwell doesn't necessarily believe / stand by what I'm saying; how could they when *I* don't even know what I'm talking about???)