ADLER1%BRANDEIS.BITNET@wiscvm.wisc.EDU (11/29/87)
I am very puzzled by the scoping rules in C. I've been looking at some code which is spread out over several files and which compiles and runs fine on various systems, including the SUN. In one file we have something like: main() { .... } routine1() { int klugec ; char **klugev ; routine2() ; ....... } In another file we have routine2() { int i ; char *s ; ........ klugev[i++] = s++ ; ........ } Everything works fine. I tried moving routine2 into the first file to make the file more self-contained and everything fell apart. The compiler complained that it did not know what klugev is in routine2. That is understandable, but I don't see what to do about it. Is there a way to tell routine2 that klugev is the variable introduced in routine1 ? The scoping rules don't seem to permit this. But then why did the program work in the first place ? Apparently the linker is compensating for what looks like a limitation on the expressive power of C. While I am happy that the linker provides some recourse, at the same time it bothers me to think that the linker must be taken into account when writing a C program. The language C is at least the subject of a proposed ANSI standard whereas I have no information about the linker. I am admittedly new at C and my naive comments could well be way off target. I welcome your comments. I would be particularly interested in knowing how to bring routine2 into the first file without substantially rewriting the code. Thank you. Sincerely, ADLER1@BRANDEIS.BITNET
chris@mimsy.UUCP (Chris Torek) (11/30/87)
In article <10575@brl-adm.ARPA> ADLER1%BRANDEIS.BITNET@wiscvm.wisc.EDU writes: >I am very puzzled by the scoping rules in C. It is quite simple, actually. The scope of a variable is the level at which it was declared, with the restriction that anything declared `static' cannot be directly referenced from outside the current file. In other words: int global; /* scope is global, but code in other files must use `extern int global' to reference this */ static int filelocal; /* code in other files cannot reference this at all */ f() /* f is global */ { int v; /* local to f */ static int s; /* local to f and other files cannot reference it, not that they could even without `static'. */ ... } static g() /* g is local to this file */ { ... } While static thus has two meanings (`make it static' and `keep it to this file'), they never conflict. >I've been looking at some code which is spread out over several >files and which compiles and runs fine on various systems, including >the SUN. [example deleted due to length; see the parent article] >Everything works fine. Then there is something that you omitted from your example; as it was, it was illegal and would not have compiled on my Sun. >Is there a way to tell routine2 that klugev is the variable introduced >in routine1? The scoping rules don't seem to permit this. That is correct: they do not. That is, there is no direct analogue to the Pascal construct procedure p; var pvar : integer; procedure q; begin pvar := 4 end; begin q end; There are efficiency reasons not to implement such scoping, and it is never necessary: it is always possible to pass the shared variable from p to q. It may be convenient at times, but C does not provide it. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
gwyn@brl-smoke.ARPA (Doug Gwyn ) (11/30/87)
In article <10575@brl-adm.ARPA> ADLER1%BRANDEIS.BITNET@wiscvm.wisc.EDU writes: >routine1() >{ > char **klugev ; > routine2() ; >} >routine2() >{ > int i ; > char *s ; > klugev[i++] = s++ ; >} [Example abridged] >Everything works fine. It shouldn't have! >The compiler complained that it did not know what klugev is in routine2. That is what it should have done in any case. >Is there a way to tell routine2 that klugev is the variable introduced >in routine1 ? The simplest way is to pass it as a parameter to the function. It could also be moved outside routine1() as a global external datum. For information on how to do this, read Kernighan & Ritchie. >But then why did the program work in the first place ? I doubt that it really "worked". One contributing factor is that use of any identifier that has not been previously declared is assumed to be a reference to an external int datum. Apparently your linker used the "common" model and allocated storage for the (undefined) external int datum klugev. However, the compiler really should not have allowed subscripting of it by an integer... (Never rely on defaults like this but always declare identifiers before using them.)