another very basic question :-)

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

    another very basic question :-)

    Hello erveryone,I am a newcomer here and the word of c.
    Here I have a question confused me a lot that when I read codes I
    found some declaration like that:
    "int regcomp(regex_t *restrict comoiled, const char *restrict
    parttern, int cflags) "
    or something like that
    " int strnlen(const char FAR *s, int count)"
    what does the "restrict" or "FAR" means?

    --thanks advance
  • James Kuyper

    #2
    Re: another very basic question :-)

    sagi wrote:
    Hello erveryone,I am a newcomer here and the word of c.
    Here I have a question confused me a lot that when I read codes I
    found some declaration like that:
    "int regcomp(regex_t *restrict comoiled, const char *restrict
    parttern, int cflags) "
    or something like that
    " int strnlen(const char FAR *s, int count)"
    what does the "restrict" or "FAR" means?
    FAR is not part of standard C. I believe that it is either a keyword or
    a macro. Either way, it only works on certain systems (which don't
    include any system I write programs for). You would get a better answer
    than I could give you by asking in a newsgroup for the appropriate
    compiler or operating system.

    To understand the restrict keyword, consider the following function. It
    takes as arguments a list of characters, and a string, and it adds 1 to
    any character in the string which matches one of the characters in the list.

    void blankchars(cons t char blanklist[], char string[])
    {
    if(blanklist == NULL || string == NULL)
    return;
    for( ; *blanklist; blanklist++)
    {
    for(size_t i=0; string[i]; i++)
    {
    if(string[i] == *blanklist)
    string[i]++;
    }
    }
    }

    What happens if this function is called as follows? :

    char alphabet[] = "abcde";
    blankchars(alph abet, alphabet);

    On my home computer, the result of this call will be that alphabet now
    contains the string "bddff". Do you understand why?

    Well, that is probably not what anyone would want the function to do. In
    fact, there's no reasonable thing for the function to do when the
    blanklist and the string overlap in any way.

    You might think that it should check for overlap between the blanklist
    and the output string. The obvious way to do this would seem to be
    compare blanklist, string, and strlen(blanklis t) and strlen(string).
    Unfortunately, if blanklist and string do NOT overlap, then comparing
    them with <, >, <=, >= or by subtracting them has behavior that is not
    defined by the C standard. On many machines it will work as you might
    expect, but on many real machines, it will produce erroneous results or
    possibly even cause your program to abort().

    You can compare pointers to different arrays for equality, and there's a
    perfectly portable way to check for overlap that makes use of that fact.
    Just compare a pointer to every character in one string for equality
    with pointers to the starting and ending characters of the other string,
    and vice versa. However, it's rather inefficient.

    The simplest approach is simply to document that the function is not
    guaranteed to work properly if there's any overlap between the strings
    pointed at by its two arguments. This is a very popular choice, and it's
    the one take by the C standard library itself in most cases like that.

    However, just because you've documented that restriction, doesn't mean
    that that compiler knows anything about it. Because you've decided not
    to worry about overlapping arguments, you could have re-written the
    innermost loop as follows:

    int c = *blanklist;

    for(size_t i; string[i]; i++)
    {
    if(string[i] == c)
    string[i] = ' ';
    }

    When there is no overlap, this code produces exactly the same result as
    the original program. This is a very simple optimization, and under
    other circumstances, virtually any modern compiler would perform
    optimizations like this one for you, even at the lowest optimization levels.

    However, in this particular circumstance, the compiler cannot perform
    this optimization for you. The compiler has to generate code which will
    work as required by the C standard, even if string[i] and *blanklist
    refer to the same character, and that's not the case for the optimized
    version of the code. With the optimized version, blankchars(alph abet,
    alphabet) would produce "fffff" (on my machine). The compiler thinks
    it's important to make sure that this case produces "bddff", and will
    therefore not perform the optimization. It doesn't know that you don't
    care about that case.

    This is where "restrict" comes in. If we change the function declaration to

    void blankchars(cons t char restrict blanklist[], char restrict string[])

    then this tells the compiler that developers and users of blankchars()
    will work together to make sure that string[i] and *blanklist never
    refer to the same object. That gives the compiler permission to perform
    optimizations like the one above.

    The down side of 'restrict' is that, if the requirements it imposes are
    violated, the behavior is undefined. It's no longer the case that we can
    say that the result of calling blankchars(alph abet, alphabet) is to set
    alphabet to "bddff". It is now technically possible that just about
    anything could happen, including causing your program to abort.

    In this particular case, it is most likely to produce "fffff", but in
    more complicated cases, the problems created by the permitted
    optimizations could be arbitrarily bad. However, to be fair, in those
    more complicated cases, the problems would probably also be pretty bad
    if the "restrict" keyword was not used.

    Comment

    • MisterE

      #3
      Re: another very basic question :-)

      sagi wrote:
      Hello erveryone,I am a newcomer here and the word of c.
      Here I have a question confused me a lot that when I read codes I
      found some declaration like that:
      "int regcomp(regex_t *restrict comoiled, const char *restrict
      parttern, int cflags) "
      or something like that
      " int strnlen(const char FAR *s, int count)"
      what does the "restrict" or "FAR" means?
      FAR (and often many other ones you will see like NEAR DATA IDATA XDATA
      RDATA etc. even FAR FAR are basically special compiler depedant things
      which tell the compiler what sort of memory is being pointed to. This
      is most common on embedded systems which can have internal RAM, external
      RAM, a second external RAM chip at different addresses etc.

      For example its typical for an embedded processor to have internal RAM
      and external ram. So you might be able to declare variables like:

      int foo[32];
      int FAR foo[32];

      one will take up space in internal ram and one in external ram, it all
      depends on the compiler. The compiler will have documentation about
      what it actually does. Typically pointers to external ram may actually
      be of different size or need to page out memory etc so they also use
      the FAR

      Comment

      • REH

        #4
        Re: another very basic question :-)

        On Sep 26, 6:04 pm, MisterE <mist...@no.ema il.okwrote:
        FAR (and often many other ones you will see like NEAR DATA IDATA XDATA
        RDATA etc. even FAR FAR are basically special compiler depedant things
        which tell the compiler what sort of memory is being pointed to. This
        is most common on embedded systems which can have internal RAM, external
        RAM, a second external RAM chip at different addresses etc.
        >
        For example its typical for an embedded processor to have internal RAM
        and external ram. So you might be able to declare variables like:
        >
        int foo[32];
        int FAR foo[32];
        >
        one will take up space in internal ram and one in external ram, it all
        depends on the compiler. The compiler will have documentation about
        what it actually does. Typically pointers to external ram may actually
        be of different size or need to page out memory etc so they also use
        the FAR
        OT, but it is more likely he is using a compiler for a segmented
        architecture, like DOS. FAR doesn't indicate any particular type of
        RAM. It indicated a far pointer, which is one that contains both the
        segment and offset of the address.

        REH

        Comment

        • Anand Hariharan

          #5
          Re: another very basic question :-)

          On Fri, 26 Sep 2008 17:51:18 +0000, James Kuyper <jameskuyper@ve rizon.net>
          wrote:

          (...)
          To understand the restrict keyword, consider the following function. It
          takes as arguments a list of characters, and a string, and it adds 1 to
          any character in the string which matches one of the characters in the
          list.
          >
          void blankchars(cons t char blanklist[], char string[]) {
          if(blanklist == NULL || string == NULL)
          return;
          for( ; *blanklist; blanklist++)
          {
          for(size_t i=0; string[i]; i++)
          {
          if(string[i] == *blanklist)
          string[i]++;
          }
          }
          }
          >
          (...)
          The simplest approach is simply to document that the function is not
          guaranteed to work properly if there's any overlap between the strings
          pointed at by its two arguments. This is a very popular choice, and it's
          the one take by the C standard library itself in most cases like that.
          >
          (...)
          This is where "restrict" comes in. If we change the function declaration
          to
          >
          void blankchars(cons t char restrict blanklist[], char restrict string[])
          >
          then this tells the compiler that developers and users of blankchars()
          will work together to make sure that string[i] and *blanklist never
          refer to the same object. That gives the compiler permission to perform
          optimizations like the one above.
          >
          The down side of 'restrict' is that, if the requirements it imposes are
          violated, the behavior is undefined.

          That was an excellent description of 'restrict', James.

          To the OP -

          'restrict' is a new feature introduced to C primarily to enable the
          compiler to perform optimisations.

          You probably need to understand what it means, since if you use a
          function whose prototype has one or more parameters qualified with
          'restrict', you need to respect it by passing the correct arguments.

          However, I suggest you to not write code that involves 'restrict' unless
          you know what you are doing.

          - Anand

          Comment

          Working...