Proper modularization technique

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • drhowarddrfine

    Proper modularization technique

    I'm unsure the best way to do this. I want to call a function that
    will generate a string to be used by the calling routine. Where is
    the best place to store that string? iow:
    1) Should I set aside an array in the calling routine and have the
    function strcpy to that?
    routine(){
    char string[16];

    called_function (string);
    }

    called_function (char* string){
    strcpy(string," string");
    }

    2) Make the string area static for the calling routine?
    routine(){
    char *string_pointer ;
    string_pointer= called_function ();
    }

    char* called_function (char* string){
    static char string[16];
    strcpy(string," string");
    return string;
    }

    3) Make the string area global to that file?
    char string[16];

    calling_routine (){called_funct ion();}
    called_function (){strcpy(strin g,"string");}

    Part 2 of this would be, I have a whole bunch of these small routines
    that need less than 256 bytes of memory for storing such strings.
    Would it be better to just malloc to acquire the memory for that and
    then release it? Does that cause relative program slow down doing all
    that acquire/releasing?
  • maverik

    #2
    Re: Proper modularization technique

    On Nov 10, 7:51 pm, drhowarddrfine <robbel...@gmai l.comwrote:
    I'm unsure the best way to do this.  I want to call a function that
    will generate a string to be used by the calling routine.  Where is
    the best place to store that string?
    There are many variants accroding to your application design at all.
    IMHO, as I understand your ideas, you can just store string within
    calling function and just return pointer:

    void
    routine() {
    char *processed = called_function (*processed);
    // you can ignore return value
    // char *processed;
    // called_function (*processed);
    ...
    // code goes here
    ...
    // Of course you must free the memory
    free(processed) ;
    }

    char*
    called_function (char * str) {
    // allocates memory
    strncpy(str, "YourString ", ...) ;
    return str;
    }

    Comment

    • maverik

      #3
      Re: Proper modularization technique

      First, I mistyped
          // called_function (*processed);
      I mean // called_function (processed);

      Second, I think that seperating allocation and deallocation is not a
      good idea. May be you should store string within the caller:

      void
      routine() {
      char *processed = malloc(...);
      if(processed == NULL) { ... }

      // Of course you may write
      // char processed[123];

      called_function (processed);
      ...
      // code goes here
      ...

      // In case of malloc
      free(processed) ;
      }

      void
      called_function (char * str) {
      strcpy(str, "YourString ") ;
      }

      What others say?

      Comment

      • Eric Sosman

        #4
        Re: Proper modularization technique

        drhowarddrfine wrote:
        I'm unsure the best way to do this. I want to call a function that
        will generate a string to be used by the calling routine. Where is
        the best place to store that string? iow:
        Much depends on your definition of "best" ...
        1) Should I set aside an array in the calling routine and have the
        function strcpy to that?
        routine(){
        char string[16];
        >
        called_function (string);
        }
        >
        called_function (char* string){
        strcpy(string," string");
        }
        This works if `16' (which probably ought to be a #define) is
        easily predictable and not over-large. The utility of returning
        a pointer to the string -- something the caller already knows --
        is questionable.

        An important variant is to let the caller manage the storage
        *and* tell the called routine how much there is:

        routine() {
        char string[HOWMANY];
        called_function (string, sizeof string);
        }

        char *called_functio n(char *string, size_t size) {
        if (strlen("string ") < size) {
        strcpy(string, "string");
        return string;
        }
        return NULL; /* means "not enough room" */
        }
        2) Make the string area static for the calling routine?
        routine(){
        char *string_pointer ;
        string_pointer= called_function ();
        }
        >
        char* called_function (char* string){
        Where did the argument come from? Copy-and-paste error?
        static char string[16];
        strcpy(string," string");
        return string;
        }
        This works if you never need more than one returned value
        at a time (or if the value is the same every time). It would
        not work well if done this way:

        char *called_functio n(int answer){
        static char string[16];
        strcpy(string, answer == 42 ? "Right!" : "Rong!");
        return string;
        }
        ...
        printf ("%s %s\n", called_function (42), called_function (24));
        3) Make the string area global to that file?
        char string[16];
        >
        calling_routine (){called_funct ion();}
        called_function (){strcpy(strin g,"string");}
        Same drawback as (2), plus the additional drawbacks of global
        variables. Globals *are* useful, sometimes, but they are very
        easy to overuse and can engender maintenance nightmares. Avoid
        them unless they're unavoidable.
        Part 2 of this would be, I have a whole bunch of these small routines
        that need less than 256 bytes of memory for storing such strings.
        Would it be better to just malloc to acquire the memory for that and
        then release it? Does that cause relative program slow down doing all
        that acquire/releasing?
        "We follow two rules in the matter of optimization:
        Rule 1. Don't do it.
        Rule 2 (for experts only). Don't do it yet - that is, not
        until you have a perfecly clear and unoptimized solution."
        -- M.A. Jackson

        It is likely that all of the approaches you mention will be faster
        than managing the memory with malloc() and free(). But here's the
        crucial question: Will their speed be enough greater to make up for
        their other drawbacks, or even enough to notice? Keep in mind all the
        other things your program is (presumably) doing, and ask yourself
        whether there might be something more important to fret about ...

        Giving your car a fresh coat of wax might reduce air resistance
        and improve the fuel economy, but taking the boat trailer off the
        back will probably improve it more.

        --
        Eric.Sosman@sun .com

        Comment

        • s0suk3@gmail.com

          #5
          Re: Proper modularization technique

          On Nov 10, 11:51 am, drhowarddrfine <robbelics@gmai l.comwrote:
          I'm unsure the best way to do this.  I want to call a function that
          will generate a string to be used by the calling routine.  Where is
          the best place to store that string?  iow:
          1) Should I set aside an array in the calling routine and have the
          function strcpy to that?
          No, because

          - the way you wrote it, called_function () will have no way to know
          how large the passed array is, and thus is likely to write pass the
          end of it. Of course, this is easily fixed by having the function
          accept an extra argument that represents the array size, but then
          there's the possibility that
          - the function might need to store more characters than the array
          can hold, thus causing truncation. If truncation isn't a problem
          (e.g., you can still get the remaining data in a future call, as with
          fgets()), then this is a good way to go.
          2) Make the string area static for the calling routine?
          No, because

          - if your application is multi-threaded, this will break things;
          - you can't have the function generate two or more strings and hold
          them at the same time (in other words, calling the function will
          modify what was previously on the array, even if you still need it);
          - there's still the issue of truncation.
          3) Make the string area global to that file?
          No, because

          - "global variables are evil." :-)
          Would it be better to just malloc to acquire the memory for that and
          then release it?  Does that cause relative program slow down doing all
          that acquire/releasing?
          That has the advantage that you can call realloc() to make the buffer
          as large as necessary. And yes, allocating on the heap is generally
          slower than allocating on the stack, but you probably don't need to
          worry about that unless you're doing micro-optimization.

          Sebastian

          Comment

          • drhowarddrfine

            #6
            Re: Proper modularization technique

            Thanks guys. You verified what I was thinking. My sample code above
            was just to give a view of what I was trying to say though I may have
            confused a little with some omissions.

            Comment

            Working...