c prog -plz explain

Discussion in 'C Programming' started by SAHIL MAHLA, Mar 10, 2014.

  1. SAHIL MAHLA

    Kaz Kylheku Guest

    Casting is the situation of actors being put into roles.

    Typecasting is when certain actors keep getting certain kinds of roles.
    (Always the bad guy, or the token representative of an ethnic group, etc.)

    Maybe this can be worked into some kind of kind of parallel in C usage.

    Discuss among yourselves ...
     
    Kaz Kylheku, Mar 12, 2014
    #21
    1. Advertisements

  2. SAHIL MAHLA

    Noob Guest

    Ergo, a simple rule for beginners would be: "Don't use casts anywhere".

    There are very few valid reasons for using casts.

    One is passing NULL to a variadic function (e.g. execl)

    Another is trying to define APIs with generic parameters (e.g. connect)
    i.e. the poor man's polymorphism.

    Regards.
     
    Noob, Mar 12, 2014
    #22
    1. Advertisements

  3. Yeah, but not in this Establishment...

    --
    "Although written many years ago, Lady Chatterley's Lover has just
    been reissued by the Grove Press, and this fictional account of the
    day-to-day life of an English gamekeeper is still of considerable
    interest to outdoor minded readers, as it contains many passages on
    pheasant raising, the apprehending of poachers, ways to control vermin,
    and other chores and duties of the professional gamekeeper.

    "Unfortunately, one is obliged to wade through many pages of extraneous
    material in order to discover and savor these sidelights on the
    management of a Midlands shooting estate, and in this reviewer's opinion
    this book cannot take the place of J.R. Miller's Practical Gamekeeping"
    (Ed Zern, Field and Stream, November 1959, p. 142).
     
    Kenny McCormack, Mar 12, 2014
    #23
  4. SAHIL MAHLA

    Kaz Kylheku Guest

    What if you're calculating i / j, where i and j are integers, and you
    want an answer like 2.75?

    No i / (double) j for you; stick with two? :)

    The stupid thing is that completely bat-shit unsafe stuff shares the same
    notation with necessary conversions.
     
    Kaz Kylheku, Mar 12, 2014
    #24
  5. Type refers to the metal objects used in mechanical printing.
    Type casting is the use of molds and molten metal to produce such objects.
     
    Lowell Gilbert, Mar 12, 2014
    #25
  6. SAHIL MAHLA

    Noob Guest

    I realize now that I only considered "pointer" casts.
    Doh!

    One trying to abide by the aforementioned "simple rule" could rely
    on implicit conversion, as in

    double d_i = i, d_j = j, res = d_i / d_j;

    But I do see your point.
    Perhaps the rule should be "Don't use pointer casts anywhere"
    Do you have other examples of reasonable use of casts?

    Regards.
     
    Noob, Mar 12, 2014
    #26
  7. SAHIL MAHLA

    Kaz Kylheku Guest

    I've been here since 1995, which makes me the Establishment; not these
    barking newcomers.

    You may use "typecast" as a synonym for "cast". Also "explicit cast" is fine,
    even though there is no "implicit cast".

    If anyone corrects you on this, and wasn't seen here before Y2K, you can safely
    tell them to **** the hell off, with my full support.

    (I would somewhat prefer that conversions that are not explicitly requested
    not be called casts. At least think about it a little, but it's your call.
    Do unions cast? You decide.)

    I also propose that "typecast" be used specifically when a value is being
    reinterpreted (type punned): that is to say, a pointer to that type is being
    cast, and the object itself (which wasn't subject to the cast notation) is
    being typecast. (If unions do cast, they definitely typecast.)

    I.e. i / (double) j is a cast, (bar_struct *) &foo_struct_obj is a typecast.
    The pointer is cast; what is typecast is foo_struct_obj itself (whose value
    is not even being accessed, let alone converted, in the cast).

    Example sentence: "In this area of the code, foo_struct_obj {is/has been}
    typecast {to/as a} bar_struct".
     
    Kaz Kylheku, Mar 12, 2014
    #27
  8. SAHIL MAHLA

    Eric Sosman Guest

    How about converting between a struct pointer and a pointer
    to the struct's first element? Or using a struct pointer and
    a byte offset to get to an element of the struct? (Both of these
    might be considered beyond the "beginner" boundary.)

    How about implementing a comparator function for qsort() or
    bsearch()? Personally, I prefer to introduce a couple helper
    variables:

    int compare(const void *pp, const void *qq) {
    const struct whatnot *p = pp, *q = qq;
    return strcmp(p->name, q->name);
    }

    .... but doing without the extra variables and applying casts
    to the arguments would be perfectly reasonable.

    Since there's no analog to `void*' for function pointers,
    casts are often necessary when dealing with pointers to functions
    of dissimilar types. (Beyond beginner boundary?)
     
    Eric Sosman, Mar 12, 2014
    #28
  9. SAHIL MAHLA

    James Kuyper Guest

    In one direction, there's a perfectly safe alternative:
    &struct_pointer->first_member (unless the struct has an opaque type -
    but it really shouldn't have an opaque type in any code that is going to
    try to access it's members). It's only going in the other direction that
    requires a cast.
    Because I prefer to treat casts as danger signs, I also prefer using the
    the helper variables.
     
    James Kuyper, Mar 12, 2014
    #29
  10. SAHIL MAHLA

    Kaz Kylheku Guest

    (out_of_the_fucking_newsgroup) useless_pedant;

    I will let you know if I think of anything else.
     
    Kaz Kylheku, Mar 12, 2014
    #30
  11. SAHIL MAHLA

    Ken Brody Guest

    On 3/12/2014 3:40 AM, Kaz Kylheku wrote:
    [...]
    float i,j;

    [...]
     
    Ken Brody, Mar 12, 2014
    #31
  12. There are enough uses for non-pointer casts that I wouldn't rule
    them out for beginners, but no good reasons that I can think of
    for pointer casts.

    -- glen
     
    glen herrmannsfeldt, Mar 12, 2014
    #32
  13. Well, first, I agree, but sometimes there are ways around it.

    If you want percentage, you can:

    pct=100.*i/j;

    no cast needed, because the multiply will force the conversion.

    Also, sometimes in the case where I want i/j not to be integer,
    it turns out to make more sense for i and/or j to be double.

    Also, often when I have i and j, I don't want i/j to be integer
    but i*(large_integer)/j to be integer. Conveniently, most processors
    allow for this. Inconveniently, C doesn't.

    -- glen
     
    glen herrmannsfeldt, Mar 12, 2014
    #33
  14. SAHIL MAHLA

    James Kuyper Guest

    On 03/12/2014 03:03 PM, glen herrmannsfeldt wrote:
    ....
    So, would you write code like the following, to avoid casts?

    double x;
    void *temp = &x;
    printf("%p\n", temp);


    Imagine that a third party library declares

    int third_party_func(char*);

    even though third_party_func() doesn't write through the char* pointer,
    it only reads from it. You don't have the influence needed to convince
    them to use "const char*" instead. Your own code has:

    const char *message = "This memory cannot be safely modified";

    How do you pass message to third_party_func()?
     
    James Kuyper, Mar 12, 2014
    #34
  15. SAHIL MAHLA

    Eric Sosman Guest

    ObPuzzle: Which of the `return' statements below is the best,
    and why?

    #include <time.h>
    /**
    * Find how many CPU seconds were consumed between
    * two values returned by clock().
    */
    double cpuSeconds(clock_t t0, clock_t t1) {
    /* A */ return (t1 - t0) / CLOCKS_PER_SEC;
    /* B */ return (t1 - t0) / (double) CLOCKS_PER_SEC;
    /* C */ return (t1 - t0) / (CLOCKS_PER_SEC + 0.0);
    }
     
    Eric Sosman, Mar 12, 2014
    #35
  16. SAHIL MAHLA

    James Kuyper Guest

    On 03/12/2014 04:05 PM, Eric Sosman wrote:
    ....
    Option A can't return fractions of a second if clock_t is an integer
    type, so I wouldn't choose that. Also, it rounds fractional parts toward
    0, whereas I prefer rounding to negative infinity.

    If clock_t is long double, option B unnecessarily discards precision in
    CLOCKS_PER_SEC, whereas option C unnecessarily discards precision in the
    final result. I think that carrying out the actual calculation in long
    double is slightly preferable, which favors C over B, but it's not a
    strong preference.

    I'd define cpuSeconds as returning long double, which would imply a
    corresponding re-write of option B. With that re-write, I'd favor B as
    the clearest of the two versions that deals correctly with the
    possibility that clock_t is an integer type.
     
    James Kuyper, Mar 12, 2014
    #36
  17. SAHIL MAHLA

    Ian Collins Guest

    Or Option D

    double cpuSeconds(clock_t t0, clock_t t1) {
    static const double clocksPerSec = CLOCKS_PER_SEC;
    return (t1 - t0) / clocksPerSec;
    }
     
    Ian Collins, Mar 12, 2014
    #37
  18. SAHIL MAHLA

    Kaz Kylheku Guest

    I would and I do. In the TXR language project, I banned void *. Generic
    pointers to anything are mem_t *, and those require casts in either direction.
    The chk_malloc function that is used everywhre returns mem_t *, and various
    other situations.

    Other than that, there is no value in being able to express a potentially
    unsafe pointer conversion without using the cast syntax, and it is wrongheaded
    to look for the ability to do such a thing for the sake of saving keystrokes.

    This is basically the same attitude which also does not want to write comments,
    or documentation.

    A cast is a remark that you put in the code that something very noteworthy is
    going on that, if bungled, could wreck the correctness of the the program, in
    exchange for the compiler making it happen without a diagnostic. That remark
    has a particular syntax, and that syntax can be found by automatic means.

    A tool that parses C can be developed which makes a report of all file names
    and line numbers where pointer casts occur. Regular expression grepping can
    almost do it, except if it is concealed by macrology.

    In other words, you're not getting rid of the diagnostic: you're just removing
    the diagnostic from the compiler output, and placing an altered representation
    of it into the code in the form of a type in parentheses. The cast is a
    diagnostic label embedded in the code. It ensures that something is written
    somewhere, addressing itself to the questionable situation.
    If you write in Clean C (code that compiles as either C or C++)
    you can do this:

    #ifdef __cplusplus
    #define REMOVE_QUAL(TYPE, PTR) (const_cast<TYPE>(PTR))
    #else
    #define REMOVE_QUAL(TYPE, PTR) ((TYPE) (PTR))
    #endif

    third_party_func(REMOVE_QUAL(char *, my_const_string));

    Suppose my_const_string is wchar_t *. It will still compile as C,
    but you will catch it when you compile as C++.
     
    Kaz Kylheku, Mar 12, 2014
    #38
  19. SAHIL MAHLA

    Ian Collins Guest

    One of the good reasons for adding the wordy casts to C++ which would
    make them a useful addition to C. Having to write nested casts to
    remove a qualifier and change a type is a good hint to developer to
    think twice about what they are doing and the reader that something out
    of the ordinary is happening.
     
    Ian Collins, Mar 12, 2014
    #39
  20. SAHIL MAHLA

    Tim Rentsch Guest

    I offer without further comment a fourth alternative:

    return (0 ? cpuSeconds(t0,t1) : t1-t0) / CLOCKS_PER_SEC;
     
    Tim Rentsch, Mar 29, 2014
    #40
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.