pls expand this macro

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

    pls expand this macro


    /*
    ** PLURALTX.C - How to print proper plurals
    ** public domain - original algorithm by Bob Stout
    */


    #include <stdio.h>


    #define plural_text(n) &"s"[(1 == (n))]

    #define plural_text2(n) &"es"[(1 == (n))<<1]

    int main(void)
    {
    int i;

    for (i = 0; i < 10; ++i)
    printf("%d thing%s in %d box%s\n", i, plural_text(i), i,
    plural_text2(i) );
    return 0;

    }

    My questions:

    1) I try to understand the two macros plural_text and plural_text2.
    array subscripting is commutative
    so in the above we could expand the macros as plural_text n[1] = "s" .
    The parenthesis around
    the variable (n) since the macros does not know the type of the variable
    it is acting on. Am I correct?

    2) I don't able to understand the use of & in both of the macros. Does
    it used for the rule "array decays into
    the pointer to it's first element"?

    3) << operator in the macro plural_text2 used to move the string to the
    second one, in the above case
    it is "s". Correct?

    Can any one explain both of the macros.
    --
    "combinatio n is the heart of chess"

    A.Alekhine

    Mail to:
    sathyashrayan AT gmail DOT com


  • Park Sung-jae

    #2
    Re: pls expand this macro

    sathyashrayan wrote:[color=blue]
    > /*
    > ** PLURALTX.C - How to print proper plurals
    > ** public domain - original algorithm by Bob Stout
    > */
    >
    >
    > #include <stdio.h>
    >
    >
    > #define plural_text(n) &"s"[(1 == (n))]
    >
    > #define plural_text2(n) &"es"[(1 == (n))<<1]
    >
    > int main(void)
    > {
    > int i;
    >
    > for (i = 0; i < 10; ++i)
    > printf("%d thing%s in %d box%s\n", i, plural_text(i), i,
    > plural_text2(i) );
    > return 0;
    >
    > }
    >
    > My questions:
    >
    > 1) I try to understand the two macros plural_text and plural_text2.
    > array subscripting is commutative
    > so in the above we could expand the macros as plural_text n[1] = "s" .
    > The parenthesis around
    > the variable (n) since the macros does not know the type of the variable
    > it is acting on. Am I correct?[/color]

    * the macro doesn't know the type of the variable.
    if you expand the macro, it looks like this

    case 1 / plural_text(0) : &"s"[0]
    ...[color=blue]
    >
    > 2) I don't able to understand the use of & in both of the macros. Does
    > it used for the rule "array decays into
    > the pointer to it's first element"?[/color]

    * "&" operand will make the right-side variable's pointer
    so it makes the array of string which started from the index value
    of the array..
    [color=blue]
    >
    > 3) << operator in the macro plural_text2 used to move the string to the
    > second one, in the above case
    > it is "s". Correct?[/color]

    * << operator shifts the result of "(1==(n))",
    so its last value is only be "0" or "2"
    "0" will be the "es"
    "2" will be the NULL

    so you can see the boxes, or box
    [color=blue]
    >
    > Can any one explain both of the macros.
    > --
    > "combinatio n is the heart of chess"
    >
    > A.Alekhine
    >
    > Mail to:
    > sathyashrayan AT gmail DOT com
    >
    >[/color]

    I'm poor at english.

    - Park, Sung-jae

    Comment

    • Walter Roberson

      #3
      Re: pls expand this macro

      In article <4364C9B9.A1BE5 2CF@REMOVETHISg mail.com>,
      sathyashrayan <sathyashrayan@ REMOVETHISgmail .com> wrote:
      [color=blue]
      >#define plural_text(n) &"s"[(1 == (n))][/color]
      [color=blue]
      >1) I try to understand the two macros plural_text and plural_text2.
      >array subscripting is commutative
      >so in the above we could expand the macros as plural_text n[1] = "s" .[/color]

      No, there is no assignment done. (1 == (n)) is an expression which
      produces a value which is either 0 or 1, and the string "s" is indexed
      at that offset, and the address (&) of the result is taken.
      &"s"[0] is a pointer to the 's' character in a string, but
      &"s"[1] is a pointer to the nul that follows the 's'.

      In other words the result is either the string "s" or the empty string.
      [color=blue]
      >3) << operator in the macro plural_text2 used to move the string to the
      >second one, in the above case
      >it is "s". Correct?[/color]

      No, treat the inside as an expression again and look at the offsets
      into the string.
      --
      I was very young in those days, but I was also rather dim.
      -- Christopher Priest

      Comment

      • Simon Biber

        #4
        Re: pls expand this macro

        sathyashrayan wrote:[color=blue]
        > /*
        > ** PLURALTX.C - How to print proper plurals
        > ** public domain - original algorithm by Bob Stout
        > */
        >
        >
        > #include <stdio.h>
        >
        >
        > #define plural_text(n) &"s"[(1 == (n))][/color]

        This is equivalent to ( "s" + (1 == (n) ) )
        ie. adding 0 or 1 to the starting address of the string literal "s". If
        adding zero, the result is a pointer to the string "s". If adding one,
        the result is a pointer to the string "".
        [color=blue]
        > #define plural_text2(n) &"es"[(1 == (n))<<1][/color]

        This is equivalent to ( "es" + (1 == (n)) * 2 )
        ie. adding 0 or 2 to the starting address of the string literal "es". If
        adding zero, the result is a pointer to the string "es". If adding two,
        the result is a pointer to the string "".
        [color=blue]
        > int main(void)
        > {
        > int i;
        >
        > for (i = 0; i < 10; ++i)
        > printf("%d thing%s in %d box%s\n", i, plural_text(i),
        > i, plural_text2(i) );
        > return 0;
        > }
        >
        > My questions:
        >
        > 1) I try to understand the two macros plural_text and plural_text2.
        > array subscripting is commutative[/color]

        That's irrelevant. This code uses array subscripting in the usual way,
        with the array on the left, and the subscript between the brackets.
        [color=blue]
        > so in the above we could expand the macros as plural_text n[1] = "s" .[/color]

        No. Not at all. The invocation
        plural_text(i)
        expands to the following eleven tokens:
        & "s" [ ( 1 == ( i ) ) ]
        [color=blue]
        > The parenthesis around
        > the variable (n) since the macros does not know the type of the variable
        > it is acting on. Am I correct?[/color]

        No. It acts on an expression, not a variable. The parenthesis are in
        case the expression given contains other operators that may affect the
        parsing.
        [color=blue]
        > 2) I don't able to understand the use of & in both of the macros. Does
        > it used for the rule "array decays into
        > the pointer to it's first element"?[/color]

        The & operator is not applied to the array. It is applied to the
        expression containing the subscript. That is, it is parsed as
        & ( "s"[(1 == (i))] )
        rather than
        (& "s") [(1 == (i))]

        Here's one way to understand it: "s" is an array of two char. That array
        is subscripted, to give an lvalue referring to either the first or
        second element of the array, and then the address-of operator is applied
        to the lvalue, giving a pointer to the first or second element of the array.
        [color=blue]
        > 3) << operator in the macro plural_text2 used to move the string to the
        > second one, in the above case
        > it is "s". Correct?[/color]

        The << operator is a binary shift on an integer value. Shifting left by
        one bit is equivalent to multiplying by two. It has the effect of
        changing a value that could be 0 or 1, into a value that could be 0 or 2
        respectively.

        --
        Simon.

        Comment

        • Netocrat

          #5
          Re: pls expand this macro

          On Sun, 30 Oct 2005 18:55:14 +0530, sathyashrayan wrote:
          [color=blue]
          > /*
          > ** PLURALTX.C - How to print proper plurals ** public domain -
          > original algorithm by Bob Stout */
          >
          >
          > #include <stdio.h>
          >
          >
          > #define plural_text(n) &"s"[(1 == (n))]
          >
          > #define plural_text2(n) &"es"[(1 == (n))<<1]
          >
          > int main(void)
          > {
          > int i;
          >
          > for (i = 0; i < 10; ++i)
          > printf("%d thing%s in %d box%s\n", i, plural_text(i), i,
          > plural_text2(i) );
          > return 0;
          >
          > }
          >
          > My questions:
          >
          > 1) I try to understand the two macros plural_text and plural_text2.
          > array subscripting is commutative
          > so in the above we could expand the macros as plural_text n[1] = "s" .[/color]

          That expansion isn't correct. In this situation, the array is "s". "s"
          is known as a string literal and here it is equivalent to a char array of
          size two, first member 's' and second member '\0' ('\0' is the string
          terminating character which is identical to integer 0, and is sometimes
          confusing referred to as NUL).

          So indexing can be applied to that array:
          "s"[0] gives the first array element, the character 's'
          "s"[1] gives the second array element, the terminating character '\0'.

          This has the same effect as first declaring:
          char str[2] = "s";
          and then indexing as:
          str[0] and str[1]

          The property of subscripting that you're referring to means that:
          str[0] is identical to writing 0[str]
          str[1] is identical to writing 1[str]
          "s"[0] is identical to writing 0["s"]
          "s"[1] is identical to writing 1["s"]
          "s"[(1 == (n))] is identical to writing (1 == (n))["s"]
          [color=blue]
          > The parenthesis around
          > the variable (n) since the macros does not know the type of the variable
          > it is acting on. Am I correct?[/color]

          The macro doesn't and can't know the type of its parameter and parentheses
          do nothing to help it. What they're actually there for is to prevent
          unintended precedence if n is a complex expression.

          It might be easier to consider a simpler situation to show why
          parenthesising macro parameters is good practice. The result of double(x
          + 1) and double_safe(x + 1) given the code below will be different, and
          only the second form will give the expected result:

          #define double(n) 2 * n
          #define double_safe(n) 2 * (n)
          int x = 1;
          [color=blue]
          > 2) I don't able to understand the use of & in both of the macros. Does
          > it used for the rule "array decays into the pointer to it's first
          > element"?[/color]

          Actually the & operator isn't making direct use of that rule. See the
          description below.
          [color=blue]
          > 3) << operator in the macro plural_text2 used to move the string to the
          > second one, in the above case
          > it is "s". Correct?[/color]

          The second macro:
          #define plural_text2(n) &"es"[(1 == (n))<<1]

          can be simplified to:
          #define plural_text2(n) &string_arra y[index]

          where string_array is "es" and index is (1 == (n))<<1

          Now consider (1 == (n))

          This will be 1 when n is 1 and 0 when n is other than 1.

          So the index will be either:
          1<<1, or 0<<1

          The first expression results in 2, and the second results in 0.

          So "es" is being indexed at 2 or 0, and then its address is taken.

          Indexing "es" at 2 results in the terminating '\0' character element, and
          the & operator returns the address of this element. The final result is
          an empty string (a pointer to a terminating character element).

          Indexing "es" at 0 results in the first character element, 'e', and the &
          operator returns the address of this element, which is the same as the
          string "es" (because being an array, "es" decays into a pointer to its
          first element - this is the rule you described).

          So when n is 1, the macro results in an empty string - which is expected -
          a single element doesn't have a plural form. When n is 0 or greater than
          1, the macro results in the string "es" - which is again expected.

          --

          Comment

          • sathyashrayan

            #6
            Re: pls expand this macro



            Simon Biber wrote:
            [color=blue]
            > sathyashrayan wrote:[color=green]
            > > /*
            > > ** PLURALTX.C - How to print proper plurals
            > > ** public domain - original algorithm by Bob Stout
            > > */
            > >
            > >
            > > #include <stdio.h>
            > >
            > >
            > > #define plural_text(n) &"s"[(1 == (n))][/color]
            >
            > This is equivalent to ( "s" + (1 == (n) ) )
            > ie. adding 0 or 1 to the starting address of the string literal "s".[/color]

            "s" is the variable at the base address of the array. == evaluates to true or
            false. So if
            the array's size should 1 as per the result of == operator evaluation. So
            ("s" + (1 == (n))) is base + index of array. Correct?

            [color=blue]
            > If
            > adding zero, the result is a pointer to the string "s". If adding one,
            > the result is a pointer to the string "".[/color]

            " " in the above sence is '\0' , nul?
            [color=blue]
            >[/color]
            [color=blue][color=green]
            > > #define plural_text2(n) &"es"[(1 == (n))<<1][/color]
            >
            > This is equivalent to ( "es" + (1 == (n)) * 2 )
            > ie. adding 0 or 2 to the starting address of the string literal "es". If
            > adding zero, the result is a pointer to the string "es". If adding two,
            > the result is a pointer to the string "".
            >[/color]
            [color=blue]
            >[color=green]
            > > int main(void)
            > > {
            > > int i;
            > >
            > > for (i = 0; i < 10; ++i)
            > > printf("%d thing%s in %d box%s\n", i, plural_text(i),
            > > i, plural_text2(i) );
            > > return 0;
            > > }
            > >
            > > My questions:
            > >
            > > 1) I try to understand the two macros plural_text and plural_text2.
            > > array subscripting is commutative[/color]
            >
            > That's irrelevant. This code uses array subscripting in the usual way,
            > with the array on the left, and the subscript between the brackets.
            >[/color]

            Macros are text replacement. So 'n' is replaced with
            &"s"[(1 == (n))]

            or simply

            "s"[0] or "es"[n*2]
            So the commutative rule does not apply hear. Correct?

            [color=blue]
            >[color=green]
            > > so in the above we could expand the macros as plural_text n[1] = "s" .[/color]
            >
            > No. Not at all. The invocation
            > plural_text(i)
            > expands to the following eleven tokens:
            > & "s" [ ( 1 == ( i ) ) ]
            >[/color]

            understood
            [color=blue]
            >[color=green]
            > > The parenthesis around
            > > the variable (n) since the macros does not know the type of the variable
            > > it is acting on. Am I correct?[/color]
            >
            > No. It acts on an expression, not a variable. The parenthesis are in
            > case the expression given contains other operators that may affect the
            > parsing.[/color]

            Arguments in macros evaluates only once for every call and also itself.
            There is a famous example covered in almost all C books about macro pit fall.
            I dont remember that at present.
            [color=blue]
            >
            >[color=green]
            > > 2) I don't able to understand the use of & in both of the macros. Does
            > > it used for the rule "array decays into
            > > the pointer to it's first element"?[/color]
            >
            > The & operator is not applied to the array. It is applied to the
            > expression containing the subscript. That is, it is parsed as
            > & ( "s"[(1 == (i))] )
            > rather than
            > (& "s") [(1 == (i))]
            >
            > Here's one way to understand it: "s" is an array of two char. That array
            > is subscripted, to give an lvalue referring to either the first or
            > second element of the array, and then the address-of operator is applied
            > to the lvalue, giving a pointer to the first or second element of the array.
            >[color=green]
            > > 3) << operator in the macro plural_text2 used to move the string to the
            > > second one, in the above case
            > > it is "s". Correct?[/color]
            >
            > The << operator is a binary shift on an integer value. Shifting left by
            > one bit is equivalent to multiplying by two. It has the effect of
            > changing a value that could be 0 or 1, into a value that could be 0 or 2
            > respectively.
            >
            > --
            > Simon.[/color]

            Thanks. I am clear with the rest of explanation.


            --
            "combinatio n is the heart of chess"

            A.Alekhine

            Mail to:
            sathyashrayan AT gmail DOT com


            Comment

            • sathyashrayan

              #7
              Re: pls expand this macro

              thanks for all the explanation.

              sathyashrayan wrote:
              [color=blue]
              > /*
              > ** PLURALTX.C - How to print proper plurals
              > ** public domain - original algorithm by Bob Stout
              > */
              >
              > #include <stdio.h>
              >
              > #define plural_text(n) &"s"[(1 == (n))]
              >
              > #define plural_text2(n) &"es"[(1 == (n))<<1]
              >
              > int main(void)
              > {
              > int i;
              >
              > for (i = 0; i < 10; ++i)
              > printf("%d thing%s in %d box%s\n", i, plural_text(i), i,
              > plural_text2(i) );
              > return 0;
              >
              > }
              >
              > My questions:
              >
              > 1) I try to understand the two macros plural_text and plural_text2.
              > array subscripting is commutative
              > so in the above we could expand the macros as plural_text n[1] = "s" .
              > The parenthesis around
              > the variable (n) since the macros does not know the type of the variable
              > it is acting on. Am I correct?
              >
              > 2) I don't able to understand the use of & in both of the macros. Does
              > it used for the rule "array decays into
              > the pointer to it's first element"?
              >
              > 3) << operator in the macro plural_text2 used to move the string to the
              > second one, in the above case
              > it is "s". Correct?
              >
              > Can any one explain both of the macros.
              > --
              > "combinatio n is the heart of chess"
              >
              > A.Alekhine
              >
              > Mail to:
              > sathyashrayan AT gmail DOT com[/color]

              --
              "combinatio n is the heart of chess"

              A.Alekhine

              Mail to:
              sathyashrayan AT gmail DOT com


              Comment

              • sathyashrayan

                #8
                Re: pls expand this macro

                [sniped...]
                [color=blue]
                >
                > Arguments in macros evaluates only once for every call and also itself.
                > There is a famous example covered in almost all C books about macro pit fall.
                > I dont remember that at present.[/color]

                netocrat explained the answer in the other thread.
                [color=blue]
                >
                >[/color]

                [

                Comment

                • Simon Biber

                  #9
                  Re: pls expand this macro

                  sathyashrayan wrote:[color=blue]
                  > Simon Biber wrote:[color=green]
                  >>sathyashray an wrote:[color=darkred]
                  >>> /*
                  >>>** PLURALTX.C - How to print proper plurals
                  >>>** public domain - original algorithm by Bob Stout
                  >>>*/
                  >>>
                  >>>#include <stdio.h>
                  >>>
                  >>>#define plural_text(n) &"s"[(1 == (n))][/color]
                  >>
                  >>This is equivalent to ( "s" + (1 == (n) ) )
                  >>ie. adding 0 or 1 to the starting address of the string literal "s".[/color]
                  >
                  > "s" is the variable at the base address of the array. == evaluates to true or
                  > false. So if
                  > the array's size should 1 as per the result of == operator evaluation. So
                  > ("s" + (1 == (n))) is base + index of array. Correct?[/color]

                  When an array is used in any expression, except as the argument of & or
                  sizeof, it is implicitly converted into a pointer to the first element
                  of an array.

                  "s" is an array. The size of the array is 2. The first element of the
                  array is (char) 's', and the second element of the array is (char) 0,
                  ie. a null character.

                  Here it is used as the argument of the [ ] operator (in the original),
                  or the + operator (in my equivalent expression), but not the & operator.
                  So, it is implicitly converted into a pointer to the first element of
                  the array. That pointer points to the 's' character.

                  If the parameter n has the value 1, then the expression (1 == (n))
                  evaluates to 1, and the result is a pointer to the second element of the
                  array, which is a null character.

                  A pointer to a null character is an empty string, and so when passed to
                  printf with the %s specifier, nothing will be printed.
                  [color=blue][color=green]
                  >>If
                  >>adding zero, the result is a pointer to the string "s". If adding one,
                  >>the result is a pointer to the string "".[/color]
                  >
                  >
                  > " " in the above sence is '\0' , nul?[/color]

                  I wrote "" (with nothing between the quotes), not " " (with a space
                  between the quotes). The result is a pointer to the null character of
                  the string "s".

                  The term "nul" is ASCII-specific, and is not the correct term used in C.
                  [color=blue][color=green][color=darkred]
                  >>>My questions:
                  >>>
                  >>>1) I try to understand the two macros plural_text and plural_text2.
                  >>>array subscripting is commutative[/color]
                  >>
                  >>That's irrelevant. This code uses array subscripting in the usual way,
                  >>with the array on the left, and the subscript between the brackets.
                  >>[/color]
                  >
                  >
                  > Macros are text replacement. So 'n' is replaced with
                  > &"s"[(1 == (n))][/color]

                  Macros are expanded as preprocessing tokens, rather than plain text, but
                  the effect is usually the same.

                  What makes you think 'n' is replaced with anything?
                  Suppose I write out the tokens, one on each line, with
                  ...
                  ...
                  ...
                  representing a sequence of zero or more tokens.

                  When the preprocessor comes across the tokens
                  plural_text
                  (
                  ...
                  ...
                  ...
                  )

                  they are replaced with
                  &
                  "s"
                  [
                  (
                  1
                  ==
                  (
                  ...
                  ...
                  ...
                  )
                  )
                  ]
                  [color=blue]
                  > or simply
                  >
                  > "s"[0] or "es"[n*2][/color]

                  No! You have left out the & operator. And n is never multiplied by 2.

                  The result of plural_text(i) is always a pointer to one of the elements
                  of the string literal "s". Either a pointer to the 's' or a pointer to
                  the null character.

                  The result of plural_text2(i) is always a pointer to one of the elements
                  of the string literal "es". Either a pointer to the 'e' or a pointer to
                  the null character.
                  [color=blue]
                  > So the commutative rule does not apply hear. Correct?[/color]

                  The commutative rule for array subscripting means that
                  array[index]
                  is equivalent to
                  index[array]

                  But in these two macros, the array is in the conventional position on
                  the left of the brackets, and the index is in the conventional position
                  between the brackets. There is no need to apply the rule.

                  --
                  Simon.

                  Comment

                  Working...