types and conversions

Discussion in 'C Programming' started by Mark, May 31, 2010.

  1. Mark

    Mark Guest

    I'm somewaht confused with what type to choose and possible conversion it
    may have to undergo. Let me explain with a real example:

    extern int read_reg(int unit, unsigned int addr, uint16_t *val);
    ....

    #define REG_PORT 0x50
    /* ports enumerate from 1 to 25 */
    extern int port_link_get(int unit, unsigned short port, int *link);

    int port_link_get(int unit, unsigned short port, int *link)
    {
    int rv;
    unsigned short addr;
    uint16_t val;

    addr = REG_PORT + ((port - 1) / 3);
    rv = read_reg(unit, addr, &val);
    ....
    return rv;
    }

    As far as I know, only in the absence of a prototype, function arguments
    unfergo default promotions. We have prototypes, so no promotion/conversion
    apply to arguments, am I tight?

    Furthemore, the second argument of 'port_link_get' is of type 'unsigned
    short', it participates in evaluating 'addr'. Will the operands of 'addr =
    ...' undergo arithmetic conversion?

    And finally 'addr' is passed to 'read_reg', where it should be converted
    (promoted?) to uint32_t. If so, it'd probably more effective to have:

    extern int port_link_get(int unit, unsigned int port, int *link);

    Are my reasonings right?
    So, if I'm on an embedded system with memory constrints, it would not be
    possible to save a few bytes by declaring 'port' argument as unsigned short
    or even unsigned char?

    What is the common sense to decide on data type, so for both effective use
    and portable?

    --
    Mark
     
    Mark, May 31, 2010
    #1
    1. Advertising

  2. Mark

    Eric Sosman Guest

    On 5/31/2010 12:37 AM, Mark wrote:
    > I'm somewaht confused with what type to choose and possible conversion
    > it may have to undergo. Let me explain with a real example:
    >
    > extern int read_reg(int unit, unsigned int addr, uint16_t *val);
    > ...
    >
    > #define REG_PORT 0x50
    > /* ports enumerate from 1 to 25 */
    > extern int port_link_get(int unit, unsigned short port, int *link);
    >
    > int port_link_get(int unit, unsigned short port, int *link)
    > {
    > int rv;
    > unsigned short addr;
    > uint16_t val;
    >
    > addr = REG_PORT + ((port - 1) / 3);
    > rv = read_reg(unit, addr, &val);
    > ....
    > return rv;
    > }
    >
    > As far as I know, only in the absence of a prototype, function arguments
    > unfergo default promotions. We have prototypes, so no
    > promotion/conversion apply to arguments, am I tight?


    Based on the loose wording and spelling errors, I'd say it's
    at least plausible that you might be tight. ;-)

    As for the rest,

    - The default argument promotions apply when there is no prototype,
    and to arguments in the "..." part of a variable-argument function
    (which must have a prototype).

    - An argument matching a prototyped parameter does not undergo the
    default argument promotions, but it *is* converted (if necessary)
    to the type specified by the prototype.

    - In your example, one such non-trivial conversion does in fact
    occur: The second argument expression in the call to read_reg()
    is of type `unsigned short', and this expression is converted
    to `unsigned int' as directed by the prototype.

    > Furthemore, the second argument of 'port_link_get' is of type 'unsigned
    > short', it participates in evaluating 'addr'. Will the operands of 'addr
    > = ..' undergo arithmetic conversion?


    It's not the same thing as the conversions that apply to function
    arguments, but yes: Conversions are at work here.

    - The parameter `port' is an `unsigned short', and the "integer
    promotions" convert it to some flavor of `int'. It might be
    to `int' or to `unsigned int' depending on the widths of `int'
    and `short' in a particular machine.

    - On machines where `unsigned short' promotes to `int', the
    right-hand side now consists entirely of `int' operands and
    the arithmetic is carried out according to `int' rules, giving
    an `int' result.

    - On machines where `unsigned short' promotes to `unsigned int',
    the right-hand side now consists of a mixture of `unsigned int'
    and plain `int' operands. The latter are all promoted to
    `unsigned int', the arithmetic is carried out according to
    `unsigned int' rules, and the result is an `unsigned int'.

    - Finally, the result (whether `int' or `unsigned int') is converted
    to `unsigned short', and `addr' receives this converted value.

    > And finally 'addr' is passed to 'read_reg', where it should be converted
    > (promoted?) to uint32_t.


    No: to `unsigned int'.

    > If so, it'd probably more effective to have:
    >
    > extern int port_link_get(int unit, unsigned int port, int *link);
    >
    > Are my reasonings right?


    I'm not sure what you mean by "more effective." "More predictable,"
    maybe, since you'd avoid the "What does `unsigned short' promote to?"
    question, essentially by forcing the expression to use `unsigned int'
    arithmetic willy-nilly. This could make a difference, for example,
    with a `port' value of zero:

    - In `int' arithmetic, the sub-expression `(port - 1) / 3' would
    evaluate as `-1 / 3' and produce zero

    - In `unsigned int' arithmetic, `(port - 1) / 3' would evaluate
    as `UINT_MAX / 3' and produce something like 21845 or 1431655765
    (these are common outcomes, other values are possible)

    > So, if I'm on an embedded system with memory constrints, it would not be
    > possible to save a few bytes by declaring 'port' argument as unsigned
    > short or even unsigned char?


    Maybe. On some machines it may take extra instructions to handle
    smaller-than-int values (sign-extending, masking, ...), so it's possible
    that space saved by shrinking the data might be lost in bloating code.
    On the other hand, some extremely low-end processors (8-bit, 4-bit, ...)
    might need multiple-precision arithmetic even for `int' calculations,
    so using a minimally-sized datum could be a win. It's entirely system-
    dependent.

    > What is the common sense to decide on data type, so for both effective
    > use and portable?


    Common sense is "Stick with `(unsigned) int' until and unless you
    have a reason to abandon it." The reason (if there is one) might be
    portable ("I need Really Big numbers") or non-portable ("My chosen CPU
    does `short' arithmetic faster/smaller/cheaper than `int', and the
    difference is large enough to worry about").

    --
    Eric Sosman
    lid
     
    Eric Sosman, May 31, 2010
    #2
    1. Advertising

  3. Mark

    Chad Guest


    >      I'm not sure what you mean by "more effective."  "More predictable,"
    > maybe, since you'd avoid the "What does `unsigned short' promote to?"
    > question, essentially by forcing the expression to use `unsigned int'
    > arithmetic willy-nilly.  This could make a difference, for example,
    > with a `port' value of zero:
    >
    >      - In `int' arithmetic, the sub-expression `(port - 1) / 3' would
    >        evaluate as `-1 / 3' and produce zero
    >
    >      - In `unsigned int' arithmetic, `(port - 1) / 3' would evaluate
    >        as `UINT_MAX / 3' and produce something like 21845 or 1431655765
    >        (these are common outcomes, other values are possible)
    >


    How do you figure that in 'int' arithmetic case, the sub-expression
    would evaluate as '-1/3', but evaluate as 'UINT_MAX/3' in the
    'unsigned int' case?
     
    Chad, May 31, 2010
    #3
  4. Mark

    Eric Sosman Guest

    On 5/31/2010 1:33 PM, Chad wrote:
    >
    >> - In `unsigned int' arithmetic, `(port - 1) / 3' would evaluate
    >> as `UINT_MAX / 3' and produce something like 21845 or 1431655765
    >> (these are common outcomes, other values are possible)
    >>

    >
    > How do you figure that in 'int' arithmetic case, the sub-expression
    > would evaluate as '-1/3', but evaluate as 'UINT_MAX/3' in the
    > 'unsigned int' case?


    What is the value of `0u - 1'?

    --
    Eric Sosman
    lid
     
    Eric Sosman, May 31, 2010
    #4
  5. Mark

    Chad Guest

    On May 31, 11:05 am, Eric Sosman <> wrote:
    > On 5/31/2010 1:33 PM, Chad wrote:
    >
    >
    >
    > >>       - In `unsigned int' arithmetic, `(port - 1) / 3' would evaluate
    > >>         as `UINT_MAX / 3' and produce something like 21845 or 1431655765
    > >>         (these are common outcomes, other values are possible)

    >
    > > How do you figure that in 'int' arithmetic case, the sub-expression
    > > would evaluate as '-1/3', but evaluate as 'UINT_MAX/3'  in the
    > > 'unsigned int' case?

    >
    >      What is the value of `0u - 1'?
    >


    Why wouldn't it be 'INT_MAX / 3' ?
     
    Chad, May 31, 2010
    #5
  6. Mark

    Eric Sosman Guest

    On 5/31/2010 2:11 PM, Chad wrote:
    > On May 31, 11:05 am, Eric Sosman<> wrote:
    >> On 5/31/2010 1:33 PM, Chad wrote:
    >>
    >>>> - In `unsigned int' arithmetic, `(port - 1) / 3' would evaluate
    >>>> as `UINT_MAX / 3' and produce something like 21845 or 1431655765
    >>>> (these are common outcomes, other values are possible)

    >>
    >>> How do you figure that in 'int' arithmetic case, the sub-expression
    >>> would evaluate as '-1/3', but evaluate as 'UINT_MAX/3' in the
    >>> 'unsigned int' case?

    >>
    >> What is the value of `0u - 1'?

    >
    > Why wouldn't it be 'INT_MAX / 3' ?


    What is the type of `port' (hint: see the O.P.'s code)?

    What type does `port' promote to (hint: see the assumption at
    the beginning of the quoted paragraph)?

    What is the type of `1'?

    What happens when the `-' operator has operands of different types?

    What are the "usual arithmetic conversions?"

    What are the "integer promotions?"

    What color are the pages of your C textbook or reference?

    Have you seen the pages with your own eyes, or are you guessing?

    --
    Eric Sosman
    lid
     
    Eric Sosman, May 31, 2010
    #6
  7. On Mon, 31 May 2010 10:33:26 -0700 (PDT), Chad <>
    wrote:

    >
    >>      I'm not sure what you mean by "more effective."  "More predictable,"
    >> maybe, since you'd avoid the "What does `unsigned short' promote to?"
    >> question, essentially by forcing the expression to use `unsigned int'
    >> arithmetic willy-nilly.  This could make a difference, for example,
    >> with a `port' value of zero:
    >>
    >>      - In `int' arithmetic, the sub-expression `(port - 1) / 3' would
    >>        evaluate as `-1 / 3' and produce zero
    >>
    >>      - In `unsigned int' arithmetic, `(port - 1) / 3' would evaluate
    >>        as `UINT_MAX / 3' and produce something like 21845 or 1431655765
    >>        (these are common outcomes, other values are possible)
    >>

    >
    >How do you figure that in 'int' arithmetic case, the sub-expression
    >would evaluate as '-1/3', but evaluate as 'UINT_MAX/3' in the
    >'unsigned int' case?


    If port is signed int and has the value 0, what is the result (type
    and value) of evaluating the parenthetical expression?

    If port is unsigned int and has the value 0, what is the result (type
    and value) of evaluating the parenthetical expression?

    --
    Remove del for email
     
    Barry Schwarz, May 31, 2010
    #7
  8. Mark

    Chad Guest

    On May 31, 11:58 am, Barry Schwarz <> wrote:
    > On Mon, 31 May 2010 10:33:26 -0700 (PDT), Chad <>
    > wrote:
    >
    >
    >
    >
    >
    > >>      I'm not sure what you mean by "more effective."  "More predictable,"
    > >> maybe, since you'd avoid the "What does `unsigned short' promote to?"
    > >> question, essentially by forcing the expression to use `unsigned int'
    > >> arithmetic willy-nilly.  This could make a difference, for example,
    > >> with a `port' value of zero:

    >
    > >>      - In `int' arithmetic, the sub-expression `(port - 1) / 3' would
    > >>        evaluate as `-1 / 3' and produce zero

    >
    > >>      - In `unsigned int' arithmetic, `(port - 1) / 3' would evaluate
    > >>        as `UINT_MAX / 3' and produce something like 21845 or 1431655765
    > >>        (these are common outcomes, other values are possible)

    >
    > >How do you figure that in 'int' arithmetic case, the sub-expression
    > >would evaluate as '-1/3', but evaluate as 'UINT_MAX/3'  in the
    > >'unsigned int' case?

    >
    > If port is signed int and has the value 0, what is the result (type
    > and value) of evaluating the parenthetical expression?
    >
    > If port is unsigned int and has the value 0, what is the result (type
    > and value) of evaluating the parenthetical expression?
    >


    I'm still not 'getting it' like what I should. Anyways, let me attempt
    to reason this out. '1' would of of type int. But port is of type
    'unsigned short'. This means port would get promoted to type 'int'. If
    port is a 'signed int' and has a value of '0', then the sub-expression
    becomes (0u - 1) / 3 or -1/3.

    Here is the part that I'm confused about. If port is of type 'unsigned
    int' and has a value of '0', then shouldn't the sub-expression become
    (0u - 1) / 3 instead of ((UINT_MAX + 1) - 1) / 3 ?
     
    Chad, May 31, 2010
    #8
  9. Chad <> writes:
    [...]
    > Here is the part that I'm confused about. If port is of type 'unsigned
    > int' and has a value of '0', then shouldn't the sub-expression become
    > (0u - 1) / 3 instead of ((UINT_MAX + 1) - 1) / 3 ?


    I haven't followed this entire discussion; I'm commenting only on the
    quoted paragraph (actually just the last line).

    Consider the subexpression (0u - 1). 0u is of type unsigned int;
    1 is of type int. The "usual arithmetic conversions" are applied
    to the operands of the "-" operator; these conversions are explained
    in detail in C99 6.3.1.8, but in this case it just means that the
    right operand is converted from int to unsigned int.

    So now we have (0u - 1u). The *mathematical* result of this subtraction
    is -1, but -1 cannot be represented directly as an unsigned int value,
    so the result is "reduced modulo the number that is one greater than the
    largest value that can be represented by the resulting type" (C99
    6.2.5p9).

    So (0u - 1) yields the value UINT_MAX of type unsigned int.

    Now we have UINT_MAX / 3. Again, the usual arithmetic conversions
    are applied, and 3 is converted from int to unsigned int; then
    the division yields a result of type unsigned int with a value
    that depends on the value of UINT_MAX (if UINT_MAX is 2**32-1,
    the result is 1431655765).

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, May 31, 2010
    #9
  10. Mark

    Chad Guest

    On May 31, 2:05 pm, Keith Thompson <> wrote:
    > Chad <> writes:
    >
    > [...]
    >
    > > Here is the part that I'm confused about. If port is of type 'unsigned
    > > int' and has a value of '0', then shouldn't the sub-expression become
    > > (0u - 1) / 3 instead of ((UINT_MAX + 1) - 1) / 3 ?

    >
    > I haven't followed this entire discussion; I'm commenting only on the
    > quoted paragraph (actually just the last line).
    >
    > Consider the subexpression (0u - 1).  0u is of type unsigned int;
    > 1 is of type int.  The "usual arithmetic conversions" are applied
    > to the operands of the "-" operator; these conversions are explained
    > in detail in C99 6.3.1.8, but in this case it just means that the
    > right operand is converted from int to unsigned int.
    >
    > So now we have (0u - 1u).  The *mathematical* result of this subtraction
    > is -1, but -1 cannot be represented directly as an unsigned int value,
    > so the result is "reduced modulo the number that is one greater than the
    > largest value that can be represented by the resulting type" (C99
    > 6.2.5p9).
    >
    > So (0u - 1) yields the value UINT_MAX of type unsigned int.
    >
    > Now we have UINT_MAX / 3.  Again, the usual arithmetic conversions
    > are applied, and 3 is converted from int to unsigned int; then
    > the division yields a result of type unsigned int with a value
    > that depends on the value of UINT_MAX (if UINT_MAX is 2**32-1,
    > the result is 1431655765).
    >


    Okay, to my defense, I wasn't aware that the result of (0u - 1u) was
    "reduced modulo the number that is one greater than the largest value
    that can be represented by the resulting type". This probably due to
    the fact that I don't have the C99 standard, and hence, haven't read
    it.
     
    Chad, Jun 1, 2010
    #10
  11. Chad <> writes:
    [...]
    > Okay, to my defense, I wasn't aware that the result of (0u - 1u) was
    > "reduced modulo the number that is one greater than the largest value
    > that can be represented by the resulting type". This probably due to
    > the fact that I don't have the C99 standard, and hence, haven't read
    > it.


    The latest post-C99 draft is freely available at
    <http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf>.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jun 1, 2010
    #11
  12. Mark

    Richard Bos Guest

    Chad <> wrote:

    > On May 31, 2:05=A0pm, Keith Thompson <> wrote:


    > > So now we have (0u - 1u). =A0The *mathematical* result of this subtraction
    > > is -1, but -1 cannot be represented directly as an unsigned int value,
    > > so the result is "reduced modulo the number that is one greater than the
    > > largest value that can be represented by the resulting type" (C99
    > > 6.2.5p9).


    > Okay, to my defense, I wasn't aware that the result of (0u - 1u) was
    > "reduced modulo the number that is one greater than the largest value
    > that can be represented by the resulting type". This probably due to
    > the fact that I don't have the C99 standard, and hence, haven't read
    > it.


    It's also in C90, as well as (logically) in K&R 2.

    Richard
     
    Richard Bos, Jun 1, 2010
    #12
  13. On May 31, 1:53 pm, Eric Sosman <> wrote:
    > On 5/31/2010 12:37 AM, Mark wrote:
    >
    >
    >
    >
    >
    > > I'm somewaht confused with what type to choose and possible conversion
    > > it may have to undergo. Let me explain with a real example:

    >
    > > extern int read_reg(int unit, unsigned int addr, uint16_t *val);
    > > ...

    >
    > > #define REG_PORT 0x50
    > > /* ports enumerate from 1 to 25 */
    > > extern int port_link_get(int unit, unsigned short port, int *link);

    >
    > > int port_link_get(int unit, unsigned short port, int *link)
    > > {
    > > int rv;
    > > unsigned short addr;
    > > uint16_t val;

    >
    > > addr = REG_PORT + ((port - 1) / 3);
    > > rv = read_reg(unit, addr, &val);
    > > ....
    > > return rv;
    > > }

    >
    > > As far as I know, only in the absence of a prototype, function arguments
    > > unfergo default promotions. We have prototypes, so no
    > > promotion/conversion apply to arguments, am I tight?

    >
    >      Based on the loose wording and spelling errors, I'd say it's
    > at least plausible that you might be tight.  ;-)
    >
    >      As for the rest,
    >
    >      - The default argument promotions apply when there is no prototype,
    >        and to arguments in the "..." part of a variable-argument function
    >        (which must have a prototype).
    >
    >      - An argument matching a prototyped parameter does not undergo the
    >        default argument promotions, but it *is* converted (if necessary)
    >        to the type specified by the prototype.
    >
    >      - In your example, one such non-trivial conversion does in fact
    >        occur: The second argument expression in the call to read_reg()
    >        is of type `unsigned short', and this expression is converted
    >        to `unsigned int' as directed by the prototype.
    >


    Sorry but I don't understand the last part: the prototype of
    'read_reg()' specifies that the type of the second parameter is
    'unsigned short'. So why is the second argument converted to 'unsigned
    int' ?

    Thanks
     
    Francis Moreau, Jun 1, 2010
    #13
  14. Mark

    Ian Collins Guest

    On 06/ 2/10 10:25 AM, Francis Moreau wrote:
    > On May 31, 1:53 pm, Eric Sosman<> wrote:
    >> On 5/31/2010 12:37 AM, Mark wrote:
    >>
    >>> I'm somewaht confused with what type to choose and possible conversion
    >>> it may have to undergo. Let me explain with a real example:

    >>
    >>> extern int read_reg(int unit, unsigned int addr, uint16_t *val);
    >>> ...

    >>
    >>> #define REG_PORT 0x50
    >>> /* ports enumerate from 1 to 25 */
    >>> extern int port_link_get(int unit, unsigned short port, int *link);

    >>
    >>> int port_link_get(int unit, unsigned short port, int *link)
    >>> {
    >>> int rv;
    >>> unsigned short addr;
    >>> uint16_t val;

    >>
    >>> addr = REG_PORT + ((port - 1) / 3);
    >>> rv = read_reg(unit, addr,&val);
    >>> ....
    >>> return rv;
    >>> }

    >>
    >>> As far as I know, only in the absence of a prototype, function arguments
    >>> unfergo default promotions. We have prototypes, so no
    >>> promotion/conversion apply to arguments, am I tight?

    >>
    >> Based on the loose wording and spelling errors, I'd say it's
    >> at least plausible that you might be tight. ;-)
    >>
    >> As for the rest,
    >>
    >> - The default argument promotions apply when there is no prototype,
    >> and to arguments in the "..." part of a variable-argument function
    >> (which must have a prototype).
    >>
    >> - An argument matching a prototyped parameter does not undergo the
    >> default argument promotions, but it *is* converted (if necessary)
    >> to the type specified by the prototype.
    >>
    >> - In your example, one such non-trivial conversion does in fact
    >> occur: The second argument expression in the call to read_reg()
    >> is of type `unsigned short', and this expression is converted
    >> to `unsigned int' as directed by the prototype.
    >>

    >
    > Sorry but I don't understand the last part: the prototype of
    > 'read_reg()' specifies that the type of the second parameter is
    > 'unsigned short'. So why is the second argument converted to 'unsigned
    > int' ?


    The OP had:

    unsigned short addr;

    rv = read_reg(unit, addr,&val)

    Where the prototype was:

    extern int read_reg(int unit, unsigned int addr, uint16_t *val);

    Hence addr is promoted from "unsigned short" to "unsigned int".

    --
    Ian Collins
     
    Ian Collins, Jun 1, 2010
    #14
  15. On Jun 2, 12:39 am, Ian Collins <> wrote:
    > On 06/ 2/10 10:25 AM, Francis Moreau wrote:
    >
    >
    >
    >
    >
    > > On May 31, 1:53 pm, Eric Sosman<>  wrote:
    > >> On 5/31/2010 12:37 AM, Mark wrote:

    >
    > >>> I'm somewaht confused with what type to choose and possible conversion
    > >>> it may have to undergo. Let me explain with a real example:

    >
    > >>> extern int read_reg(int unit, unsigned int addr, uint16_t *val);
    > >>> ...

    >
    > >>> #define REG_PORT 0x50
    > >>> /* ports enumerate from 1 to 25 */
    > >>> extern int port_link_get(int unit, unsigned short port, int *link);

    >
    > >>> int port_link_get(int unit, unsigned short port, int *link)
    > >>> {
    > >>> int rv;
    > >>> unsigned short addr;
    > >>> uint16_t val;

    >
    > >>> addr = REG_PORT + ((port - 1) / 3);
    > >>> rv = read_reg(unit, addr,&val);
    > >>> ....
    > >>> return rv;
    > >>> }

    >
    > >>> As far as I know, only in the absence of a prototype, function arguments
    > >>> unfergo default promotions. We have prototypes, so no
    > >>> promotion/conversion apply to arguments, am I tight?

    >
    > >>       Based on the loose wording and spelling errors, I'd say it's
    > >> at least plausible that you might be tight.  ;-)

    >
    > >>       As for the rest,

    >
    > >>       - The default argument promotions apply when there is no prototype,
    > >>         and to arguments in the "..." part of a variable-argument function
    > >>         (which must have a prototype).

    >
    > >>       - An argument matching a prototyped parameter does not undergo the
    > >>         default argument promotions, but it *is* converted (if necessary)
    > >>         to the type specified by the prototype.

    >
    > >>       - In your example, one such non-trivial conversion does in fact
    > >>         occur: The second argument expression in the call to read_reg()
    > >>         is of type `unsigned short', and this expression is converted
    > >>         to `unsigned int' as directed by the prototype.

    >
    > > Sorry but I don't understand the last part: the prototype of
    > > 'read_reg()' specifies that the type of the second parameter is
    > > 'unsigned short'. So why is the second argument converted to 'unsigned
    > > int' ?

    >
    > The OP had:
    >
    > unsigned short addr;
    >
    > rv = read_reg(unit, addr,&val)
    >
    > Where the prototype was:
    >
    > extern int read_reg(int unit, unsigned int addr, uint16_t *val);
    >
    > Hence addr is promoted from "unsigned short" to "unsigned int".


    Damn I mis read the prototypes.

    Sorry for the noise.
     
    Francis Moreau, Jun 2, 2010
    #15
    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. jeffc
    Replies:
    4
    Views:
    2,788
    jeffc
    Dec 9, 2004
  2. Replies:
    10
    Views:
    722
    Jasen Betts
    Aug 5, 2005
  3. MikeL
    Replies:
    2
    Views:
    299
    Dino Chiesa [Microsoft]
    Feb 22, 2005
  4. ittium
    Replies:
    4
    Views:
    328
    Goran
    Dec 9, 2011
  5. Sam Kong
    Replies:
    12
    Views:
    303
    John G Harris
    Oct 17, 2006
Loading...

Share This Page