A couple of C style/semantics questions about variables

Discussion in 'Mac Programming' started by Sydde, May 10, 2011.

  1. macrumors 68000

    Sydde

    Joined:
    Aug 17, 2009
    #1
    These are pretty trivial things:

    In Objective C, you might observe something in a .m file that looks like

    Code:
    #import ThisClass.h
    
    static id theSingletonInstance = nil;
    
    @implementation ThisClass
    ...
    
    @end
    Which puts a variable (theSingletonInstance) in a specific location where code will be able to find it. But this declaration is outside any { scope }, so it is obviously not automatic. If you omit "static", what changes? I ask because I was once working on a program that had variables declared in a .h file, without the static specification, and they were, well, static.


    Secondly, I am curious how people feel about using arguments as locals. As far as I can tell, they live on the stack, just above the return vector (or sometimes in registers, as with PPC) and C subroutines, as I read once long ago, do not clean up the stack upon return, so the caller might leave the argument frame in place if the subroutine is being called repeatedly in a loop (compiler optimization, perhaps). But really, how dangerous is it to alter the local value of arguments, once you no longer need the originals? Is it considered bad practice?
     
  2. jiminaus, May 10, 2011
    Last edited: May 10, 2011

    macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #2
    Static at this level means something different then static does within the {} of a function or method. At this level, static means the variable is only accessible/visible within the current compilation unit, the current .m file in this context; that is the symbol is not exported and make visible to the linker. Without the static, the variable symbol would be exported publicly in the .o file and could be referred to in other in other compilation units. The linker in this case would resolve the external symbol in the other .o files by joining them to this exported symbol.

    Furthermore, if you had another singleton class in another .m file that followed this same pattern of having a theSingletonInstance global variable, you'd get a linker error if they weren't both static, because the symbol theSingletonInstance would be defined and exported twice in two different .o files.


    In the C calling convention, it is the callee's responsibility to clean up the static after a call. But assuming someone's not hacking in assembler and just leaving the compiler to generate this code, I wouldn't be concerned with it. [EDIT: Callee should be caller in the paragraph.]

    There's no danger is changing the local value of argument in terms of the stack. The only "danger" is if one expected the value to be changed in the callee as well.

    Style-wise is another purely subjective story. Personally I was heavily influence by function programming, so I avoid changing the values of variables. I would be more inclined to assign the new value to a new variable, and let the compiler optimise it away, if necessary.
     
  3. thread starter macrumors 68000

    Sydde

    Joined:
    Aug 17, 2009
    #3
    That seems odd to me. I would have expected variables to require explicit inclusion in order to be reachable across files (e.g., in a .h file). This highlights one advantage of Objective-C, being able to create long-lived private variable context.
    Well, OK, I just tried that (one static, one not), got no warning from the linker (building from XCode), and the variables were the same entity. I shall henceforth be very careful with statics. It seems much safer to keep variables within object contexts.
    Hmm, that is not what I remember reading in IM (volume three, I think). I was writing in ML for my own amusement, so I had to understand calling conventions like that. That, and/or some other text, told me that C and Pascal had opposite argument order (classic Mac OS used the Pascal convention) and that Pascal expected stack clean-up upon return while C did not. Perhaps I was misinformed or misunderstood.
    I am heavily influenced by laziness. It seems like it could make sense to provisionally alter the argument value (e.g., to modify a path) in the first part of a routine and let the second part handle what it gets in that argument. But again, as you say, it is a matter of style.
     
  4. macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #4
    You right. Pascal and C are opposite. Sorry I wrote callee and when I meant caller. See http://en.wikipedia.org/wiki/X86_calling_conventions.
     
  5. macrumors 603

    Joined:
    Aug 9, 2009
    #5
    Any variables declared as static are invisible outside the declaring compilation unit. So the fact that one is static automatically means that the "one not" is the sole externally visible variable. Thuse there is no conflict and no warning.

    There is no need to "be very careful with statics", as long as you use the 'static' keyword. That's the purpose of the keyword: to restrict the scope.

    If you want to cause an error, you'll have to try it with at least two variables without a 'static' qualifier.

    You may also have to provide an initializer for both variables. It is not uncommon for code like this:
    Code:
    foo.c:
    int foo;
    
    bar.c:
    int foo = 1;
    
    to be treated by the compiler and linker like this:
    Code:
    foo.c:
    extern int foo;
    
    bar.c:
    int foo = 1;
    
    In other words, there is a single int variable named foo, which is initialized to 1 in bar.c. As long as there isn't a conflicting type or initializer, the linker may successfully turn the multiple definitions into a single consistent global variable with a uniquely determined initializer.

    In olden tymes, the linker was dumber, and would only complain about multiple attempts to initialize the variable. It was ignorant of type, so it was possible to have extern int foo in one file and extern float foo in another, with exciting debugging sessions as a result.
     
  6. macrumors 6502

    Joined:
    Apr 24, 2008
    #6
    In fact, the C99 standard specifies this (6.2.2, paragraph 5): "If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external."

    The word "static" is a bit overloaded in C. Where it is used to restrict scope to the current translation unit, perhaps a better keyword would have been "local". And arguably, this should have been the default behavior, requiring explicit confirmation to make objects visible outside. Perhaps even for functions - we'd be half-way to an object oriented programming language then :)
     
  7. thread starter macrumors 68000

    Sydde

    Joined:
    Aug 17, 2009
    #7
    Well, why not simply "private"(default)/"public", that seems clear enough, no?
     

Share This Page