stdbool.h

Discussion in 'C Programming' started by Jorgen Grahn, Mar 1, 2014.

  1. You mean that they are more complex machines than the ones we make.
    It is because they are "not machines" that they should be able to think
    about what other human readers will make of their code. A thoughtful
    programmer will see that 'true' is exactly as descriptive as 42 -- no
    more and no less. Are there some who will pepper their code with 42s
    regardless of good practice? Yes. Are there some who will give 42 a
    name but yet still pass true and false where the meaning is unclear?
    Apparently there are. The advice should be to include all such
    constants in the advice about not having magic constants in code.
    And in that case they are correct. There is no need to name those
    instances. There are analogous situations for other types as well. You
    will find good quality code that has i+1 and j-1 in it. The context
    will often remove the need to name the constant. It's a judgement made
    by people who are not acting like machines.
    I don't get this point at all. Why would you do that? Are you giving
    an example of a bad API in order to make some general point?
     
    Ben Bacarisse, Mar 2, 2014
    #21
    1. Advertisements

  2. Jorgen Grahn

    Stefan Ram Guest

    The first comparison is not fair because it uses literals
    for the booleans and names for everything else. Compare
    literals with literals or names with names.

    »SD_POPULATION« is no good boolean name. A good boolean name
    would be »is_...«, »has_...«, »...able«, or an imperative.
    A population is not boolean.
     
    Stefan Ram, Mar 2, 2014
    #22
    1. Advertisements

  3. A standard deviation is a measure of spread. If you can measure the entire
    population, it's defined as root mean squared difference from the mean.
    If you can only measure a sample, it's one less in the denominator, i.e
    you divide by N-1 instead of N when taking the mean.
    So there are two options, and pretty much everyone who writes a standard
    deviation routine will want to provide a way of choosing one of them.
    It's unlikely that someone will invent another measure of spread that
    constitutes a third option, because you inherently have either an entire
    population or a sample from that population.
    So you can argue about whether the third parameter is philosophically boolean
    or an enumeration that happens to have two values. I'm not taking a position
    on that, simply noting that C doesn't allow the syntax

    sd = standard_deviation( values = x, count = N, issample = false)

    you can of course put comments, but that's unlikely to happen.

    The third parameter could just as logically be ispopulation as issample
    I suppose you could have another philosophical argument about whether a
    population or a sample is the more basic type and the natural boolean
    representation for that.
     
    Malcolm McLean, Mar 2, 2014
    #23
  4. We could reasonably do this

    #define CONTROL_DISABLE 123
    #define CONTROL_ENABLE 42

    /* pass CONTROL_DISABLE or CONTROL_ENABLE */
    void EnableControl(int action);

    Now very few programmers would be stupid enough to pass a raw 42.

    However if we declare the function as taking a bool, the same programmer
    might well pass true and false. When you see
    EnableControl(false)
    or worse
    EnableControl(0);
    in code you're debugging, then that might well be confusing.
     
    Malcolm McLean, Mar 2, 2014
    #24
  5. Jorgen Grahn

    Stefan Ram Guest

    In Java, there is a method with the signature
    »javax.swing.Timer.setLogTimers( boolean )«.

    Following this example, we can use the name »setControlEnabled«:

    setControlEnabled( false );
    setControlEnabled( 0 );

    , which is passably readable.
     
    Stefan Ram, Mar 2, 2014
    #25
  6. Jorgen Grahn

    Stefan Ram Guest

    This thread is about stdbool.h, so I was reading it as bool.

    Philosophically, an enumeration would be better, because
    it would keep the symmetry between the two possibilities.

    One also might use two function names:

    standard_sample_deviation( N, x )
    standard_population_deviation( N, x )

    . A more elaborate approach might have x be a statistical
    value container (struct), which already knows whether it is
    a sample or the whole population and how many entries it
    contains. In this case,

    standard_deviation( x )

    alone would suffice.
     
    Stefan Ram, Mar 2, 2014
    #26
  7. But you often need "propagate" flags when setting values on user interface
    elements. The reason is that often you want to set a whole series of states
    in response to the user or a third party disabling the control, and it's
    very easy to end up in a infinite recursion if you set in response to a
    set notifier.
    So if you're not familiar, there's no way of knowing if
    setControlEnabled(false) is one function which andles the enable/disable
    case, or one of a pair of functions which takes a propagate flag.

    One general problem with software engineering is that snippets seldom
    illustrate real problems well. Any halfway sensible convention or interface
    seems ok when you've only half a dozen lines of code to look at. The
    difference etween a good design and a bad design only becomes apparent
    when you're dealing with real preograms,
     
    Malcolm McLean, Mar 2, 2014
    #27
  8. Jorgen Grahn

    Ian Collins Guest

    They won't provide #constants because C has moved on form the 80s. We
    have const now.
     
    Ian Collins, Mar 2, 2014
    #28
  9. Jorgen Grahn

    Kaz Kylheku Guest

    It's an argument against boolean parameters for which constants are expectd to
    be used in 90% of the calls.

    Quick, what kind of event does this create in Windows:

    CreateEvent(NULL, FALSE, FALSE, NULL);

    The proper documentation is there; the problem is I have to go look at it.

    It's tempting to make meaningful synonyms for the booleans. Trobule is there is no
    type checking.

    Suppose we do this:

    #define EV_MANUAL_RESET TRUE
    #define EV_AUTO_RESET FALSE
    #define EV_INITIALY_SET TRUE
    #define EV_INITIALY_RESET FALSE

    We can now mix up the order, without any diagnostics from the compiler:

    CreateEvent(NULL, EV_INITIALLY_SET, AV_AUTO_RESET, NULL);

    Oops! So we still have to check the documentation to get the order right.

    When we have ensured that, the readability improvement is undeniable, though.
     
    Kaz Kylheku, Mar 2, 2014
    #29
  10. const is not a C99-specific feature; it was added in C89.
     
    Keith Thompson, Mar 2, 2014
    #30
  11. In C++, `1==2` has type bool. In C, it has type int. C++'s bool type
    is much more tightly integrated into the language than C's _Bool.
     
    Keith Thompson, Mar 2, 2014
    #31
  12. More to the point, we have enum.
     
    Keith Thompson, Mar 2, 2014
    #32
  13. Jorgen Grahn

    Eric Sosman Guest

    ... which I once saw used (in the pre-C99 days) as

    typedef enum { TRUE, FALSE } Boolean;

    There was much teething of gnash and hairing of tear when
    this little earth was ungemmed.
     
    Eric Sosman, Mar 2, 2014
    #33
  14. Stephen Sprunk, Mar 2, 2014
    #34
  15. Jorgen Grahn

    James Kuyper Guest

    On 03/02/2014 06:35 AM, Jorgen Grahn wrote:
    ....
    You make it sound like _Bool could simply be another name for 'int', or
    at least for a type that is handled internally the same way that 'int',
    but that's not the case, for three reasons:

    * sizeof(_Bool) is not required to match sizeof(int).

    * _Bool has a lower integer conversion rank than an other integer type.

    * Conversion of a value x of any scalar type to _Bool produces a result
    that's 0 if x compares equal to 0, and otherwise produces a result of 1.

    * It's not a constraint violation for a _Bool to be the left operand of
    an assignment statement when the right operand has pointer type.
     
    James Kuyper, Mar 3, 2014
    #35
  16. Right, but I note in passing that the function names are wrong (or maybe
    just bad).
    That's pretty much what you said before. What I don't get is the point
    you are making. If the function name makes sense with a bool argument
    (as in your last example) then what's the problem with passing a
    literal? If the function names don't convey what they should then you
    simply have a bad API. I don't see any problem that has anything to do
    with bool.
     
    Ben Bacarisse, Mar 3, 2014
    #36
  17. Jorgen Grahn

    David Brown Guest

    That is an argument for why C could really benefit from named parameters
    to functions, so that we could write:

    CreateEvent(.lpEventAttributes = NULL, .bManualReset = true,
    ..bInitialState = false, .lpName = NULL);
     
    David Brown, Mar 3, 2014
    #37
  18. Jorgen Grahn

    David Brown Guest

    You /can/ do this sort of thing - but it is an ugly mess and cannot be
    mixed with normal function syntax. My wish would be that given the
    normal declaration of a function, you could then use named parameters as
    an when you want, and mix them with positional ones. As long as the
    syntax does not conflict with existing C syntax (that's why I suggest
    putting a "." before the parameter name), I believe it would be simple
    syntactic sugar. I also think it would work in C++ too (although
    complications like templates, default arguments, overloading, etc.,
    would mean there is more to check). There certainly seems to be no
    problem with them in other languages (Python, C#, etc.).
    Even for a function with only a few arguments, named arguments can make
    the code clearer. And having them as a language features makes them
    zero cost (in run-time, code time, and in source code size and effort) -
    you use them if you want to.
     
    David Brown, Mar 3, 2014
    #38
  19. Jorgen Grahn

    Jorgen Grahn Guest

    That wasn't my intention. I meant something more like "moving to
    _Bool isn't a radical step".
    That's one of the featues I'm after. Last year I helped create
    this bug:

    our_bool_t foo = (bar & MASK);

    our_bool_t was an unsigned char, and MASK had only higher bits set.
    Oops! Fortunately it was quickly found in testing.
    /Jorgen
     
    Jorgen Grahn, Mar 3, 2014
    #39
  20. You're assuming that we can find programmers with English literature degrees
    who understand clear communication, and also of course technical degrees
    so they understand the mathematical side of what they are doing.
    You can maybe get the odd such person. But, generally, a name like
    EnableControl() is meaningful to the person writing the function. Enabling
    shares substantial logic with disabling, so it's easier to provide the same
    function. And we've only got one control.
    But to the maintaining programmer

    EnableControl(0);

    might mean "enable control with index zero". He knows we've
    only got one control. Fair enough, that's in for expansion.

    I chose EnableControl() because it's a common real example. Plenty of APIs
    have it.

    With software engineering, the trivial is important. It's not so much than
    any one feature is unacceptably bad. It's the interaction of such features.

    Consider this.

    SetControlState(CONTROL_DISABLED);

    acceptable, but a bit confusing, because you can't pass anything except
    CONTROL_ENABLED or CONTROL_DISABLED.

    Now

    SetControlState(true);

    the reader is completely in the dark. The bool has interacted with a poor
    choice of name to make something very confusing.
     
    Malcolm McLean, Mar 4, 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.