pls expand this macro

Discussion in 'C Programming' started by sathyashrayan, Oct 30, 2005.

  1. /*
    ** 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.
    --
    "combination is the heart of chess"

    A.Alekhine

    Mail to:
    sathyashrayan AT gmail DOT com
    sathyashrayan, Oct 30, 2005
    #1
    1. Advertising

  2. sathyashrayan wrote:
    > /*
    > ** 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?


    * 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]
    ...
    >
    > 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"?


    * "&" 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..

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


    * << 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

    >
    > Can any one explain both of the macros.
    > --
    > "combination is the heart of chess"
    >
    > A.Alekhine
    >
    > Mail to:
    > sathyashrayan AT gmail DOT com
    >
    >


    I'm poor at english.

    - Park, Sung-jae
    Park Sung-jae, Oct 30, 2005
    #2
    1. Advertising

  3. In article <>,
    sathyashrayan <> wrote:

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


    >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" .


    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.

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


    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
    Walter Roberson, Oct 30, 2005
    #3
  4. sathyashrayan

    Simon Biber Guest

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


    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 "".

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


    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 "".

    > 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


    That's irrelevant. This code uses array subscripting in the usual way,
    with the array on the left, and the subscript between the brackets.

    > so in the above we could expand the macros as plural_text n[1] = "s" .


    No. Not at all. The invocation
    plural_text(i)
    expands to the following eleven tokens:
    & "s" [ ( 1 == ( i ) ) ]

    > The parenthesis around
    > the variable (n) since the macros does not know the type of the variable
    > it is acting on. Am I correct?


    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.

    > 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"?


    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.

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


    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.
    Simon Biber, Oct 30, 2005
    #4
  5. Simon Biber wrote:

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

    >
    > This is equivalent to ( "s" + (1 == (n) ) )
    > ie. adding 0 or 1 to the starting address of the string literal "s".


    "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?


    > If
    > adding zero, the result is a pointer to the string "s". If adding one,
    > the result is a pointer to the string "".


    " " in the above sence is '\0' , nul?

    >


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

    >
    > 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 "".
    >


    >
    > > 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

    >
    > That's irrelevant. This code uses array subscripting in the usual way,
    > with the array on the left, and the subscript between the brackets.
    >


    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?


    >
    > > so in the above we could expand the macros as plural_text n[1] = "s" .

    >
    > No. Not at all. The invocation
    > plural_text(i)
    > expands to the following eleven tokens:
    > & "s" [ ( 1 == ( i ) ) ]
    >


    understood

    >
    > > The parenthesis around
    > > the variable (n) since the macros does not know the type of the variable
    > > it is acting on. Am I correct?

    >
    > 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.


    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.

    >
    >
    > > 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"?

    >
    > 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.
    >
    > > 3) << operator in the macro plural_text2 used to move the string to the
    > > second one, in the above case
    > > it is "s". Correct?

    >
    > 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.


    Thanks. I am clear with the rest of explanation.


    --
    "combination is the heart of chess"

    A.Alekhine

    Mail to:
    sathyashrayan AT gmail DOT com
    sathyashrayan, Oct 30, 2005
    #5
  6. sathyashrayan

    Netocrat Guest

    On Sun, 30 Oct 2005 18:55:14 +0530, sathyashrayan wrote:

    > /*
    > ** 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" .


    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"]

    > The parenthesis around
    > the variable (n) since the macros does not know the type of the variable
    > it is acting on. Am I correct?


    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;

    > 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"?


    Actually the & operator isn't making direct use of that rule. See the
    description below.

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


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

    can be simplified to:
    #define plural_text2(n) &string_array[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.

    --
    http://members.dodo.com.au/~netocrat
    Netocrat, Oct 30, 2005
    #6
  7. thanks for all the explanation.

    sathyashrayan wrote:

    > /*
    > ** 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.
    > --
    > "combination is the heart of chess"
    >
    > A.Alekhine
    >
    > Mail to:
    > sathyashrayan AT gmail DOT com


    --
    "combination is the heart of chess"

    A.Alekhine

    Mail to:
    sathyashrayan AT gmail DOT com
    sathyashrayan, Oct 30, 2005
    #7
  8. [sniped...]

    >
    > 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.


    netocrat explained the answer in the other thread.

    >
    >


    [
    sathyashrayan, Oct 30, 2005
    #8
  9. sathyashrayan

    Simon Biber Guest

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

    >>
    >>This is equivalent to ( "s" + (1 == (n) ) )
    >>ie. adding 0 or 1 to the starting address of the string literal "s".

    >
    > "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?


    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.

    >>If
    >>adding zero, the result is a pointer to the string "s". If adding one,
    >>the result is a pointer to the string "".

    >
    >
    > " " in the above sence is '\0' , nul?


    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.

    >>>My questions:
    >>>
    >>>1) I try to understand the two macros plural_text and plural_text2.
    >>>array subscripting is commutative

    >>
    >>That's irrelevant. This code uses array subscripting in the usual way,
    >>with the array on the left, and the subscript between the brackets.
    >>

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


    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
    ==
    (
    ...
    ...
    ...
    )
    )
    ]

    > or simply
    >
    > "s"[0] or "es"[n*2]


    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.

    > So the commutative rule does not apply hear. Correct?


    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.
    Simon Biber, Oct 31, 2005
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. MiniDisc_2k2

    Re: Expand macro's

    MiniDisc_2k2, Jul 22, 2003, in forum: C++
    Replies:
    4
    Views:
    516
    Stewart Gordon
    Jul 22, 2003
  2. Victor Bazarov

    Re: Expand macro's

    Victor Bazarov, Jul 22, 2003, in forum: C++
    Replies:
    0
    Views:
    409
    Victor Bazarov
    Jul 22, 2003
  3. Guy Harrison

    Re: Expand macro's

    Guy Harrison, Jul 22, 2003, in forum: C++
    Replies:
    0
    Views:
    369
    Guy Harrison
    Jul 22, 2003
  4. Fabrice
    Replies:
    12
    Views:
    540
    Keith Thompson
    Nov 1, 2007
  5. Doug .

    C macro to expand struct types?

    Doug ., Jul 1, 2011, in forum: C Programming
    Replies:
    1
    Views:
    1,202
    Shao Miller
    Jul 3, 2011
Loading...

Share This Page