[META] Talking about talking about C.

Discussion in 'C Programming' started by Seebs, Oct 23, 2010.

  1. Seebs

    Seebs Guest

    So, watching the typedef battles, something has become clear to me.

    Engineers suck at communicating.

    Underneath it all, it is perhaps useful to remember that most of the
    active participants here are people who have successfully written reasonably
    large programs in C, so however they're thinking about C inside their heads,
    it *works*. Maybe it's not exactly correct, but at the bare minimum, you
    can be reasonably confident that it's a good enough model to have both
    explanatory and predictive power for the behavior of programs on real
    machines.

    One of the most useful non-engineering skills I've ever applied to engineering
    is learning to communicate better. Interestingly, writing clearly, while
    certainly useful, is by far the lesser part of this. The big thing is to
    learn to listen better. And I still have a long way to go on that.

    A friend of mine gave me an excellent summary of a useful tactic when someone
    who is otherwise apparently pretty rational or well-informed says something
    obviously false:
    Rather than thinking of it as false, think of it as true, and try
    to figure out what it could be true *of*.

    That's certainly contrary to the way engineers usually think! However, it's
    very useful.

    Here's an example of how I might apply that. It is obvious to me that size_t
    is distinct from any of the standard unsigned integer types. Someone comes
    along and tells me that size_t is the same as one of those types. Obviously
    this is untrue... But wait! He's no idiot. What's he talking about?

    Well, it turns out, what he's saying is quite true if, instead of talking
    about the abstract language spec, I talk about any real implementation I've
    ever heard of. On any real implementation I've seen, size_t is the same
    type as one of unsigned short, unsigned int, unsigned long, or unsigned long
    long. I've never heard of an exception. So actually, he's saying something
    true, but he's talking about something other than what I'm talking about. If
    I understand this, I can get somewhere. If I don't, I'm going to spend a
    lot of time telling him that he's wrong, which he's not going to believe,
    because he's tested his claim and it's obviously true.

    Once we've got that figured out, we can potentially have a productive
    discussion about whether it's more useful or effective to think about types
    in terms of logical types or in terms of the compatibility rules that
    are invoked when you try to assign a 'foo *' to a 'bar *'. Both ways of
    thinking about types work. You can write large programs thinking about
    it either way. Furthermore, each way of thinking about types will expose
    you to some problems -- which the other avoids.

    The same thing comes up when, say, someone talks about "the stack". All
    the experienced C programmers know that C doesn't have a stack, except the
    ones who know that C does have a stack. There are at least three reasonably
    plausible ways of thinking about this. You can treat it as a contiguous
    block of memory which always grows in the same direction. Sure, it's not
    exactly right, but it'll work well enough most of the time, and it's simple.
    You can treat it as totally separate activation records. You can think of
    it more like a LIFO queue, without any regard to how it goes together.

    All of these models *work*. None of them are exactly mandated. If, instead
    of calling people "wrong" when they use a different model, you try to
    understand the model they're using and see how it could be useful to you,
    you're more likely to learn something.

    Learning to distinguish between the thing you're modeling, and your model
    of it, is really useful. It can make you a better programmer. It can
    also reduce, dramatically, the number of clueless jerks you encounter on
    Usenet.

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
    Seebs, Oct 23, 2010
    #1
    1. Advertising

  2. Re: Talking about talking about C.

    On 23 Oct, 19:44, Seebs <> wrote:
    > So, watching the typedef battles, something has become clear to me.
    >
    > Engineers suck at communicating.
    >


    No, everyone sucks at communicating.

    > A friend of mine gave me an excellent summary of a useful tactic when someone
    > who is otherwise apparently pretty rational or well-informed says something
    > obviously false:
    >         Rather than thinking of it as false, think of it as true, and try
    >         to figure out what it could be true *of*.
    >


    Much too absolute. If someone says that all crows are white, it is
    false. It's the height of impertinence to nod patronisingly while
    deciding inwardly that they're actually talking about polar bears.

    > Here's an example of how I might apply that.  It is obvious to me that size_t
    > is distinct from any of the standard unsigned integer types.


    No, no! It's distinct from *all but one* of the standard unsigned
    integer types.

    > All of these models *work*.  None of them are exactly mandated.  If, instead
    > of calling people "wrong" when they use a different model, you try to
    > understand the model they're using and see how it could be useful to you,
    > you're more likely to learn something.
    >


    People will no more agree that they are arguing about different
    "models" than they will agree that they are arguing about different
    "subjectivities".

    Martin
    MartinBroadhurst, Oct 23, 2010
    #2
    1. Advertising

  3. Seebs <> writes:
    > So, watching the typedef battles, something has become clear to me.
    >
    > Engineers suck at communicating.
    >
    > Underneath it all, it is perhaps useful to remember that most of the
    > active participants here are people who have successfully written reasonably
    > large programs in C, so however they're thinking about C inside their heads,
    > it *works*. Maybe it's not exactly correct, but at the bare minimum, you
    > can be reasonably confident that it's a good enough model to have both
    > explanatory and predictive power for the behavior of programs on real
    > machines.
    >
    > One of the most useful non-engineering skills I've ever applied to engineering
    > is learning to communicate better. Interestingly, writing clearly, while
    > certainly useful, is by far the lesser part of this. The big thing is to
    > learn to listen better. And I still have a long way to go on that.
    >
    > A friend of mine gave me an excellent summary of a useful tactic when someone
    > who is otherwise apparently pretty rational or well-informed says something
    > obviously false:
    > Rather than thinking of it as false, think of it as true, and try
    > to figure out what it could be true *of*.
    >
    > That's certainly contrary to the way engineers usually think! However, it's
    > very useful.


    Well said. I probably haven't worked hard enough at this myself in the
    typedef thread.

    Of course I can't resist the urge to quibble with some of the details
    even in this post. :cool:}

    > Here's an example of how I might apply that. It is obvious to me that size_t
    > is distinct from any of the standard unsigned integer types. Someone comes
    > along and tells me that size_t is the same as one of those types. Obviously
    > this is untrue... But wait! He's no idiot. What's he talking about?
    >
    > Well, it turns out, what he's saying is quite true if, instead of talking
    > about the abstract language spec, I talk about any real implementation I've
    > ever heard of. On any real implementation I've seen, size_t is the same
    > type as one of unsigned short, unsigned int, unsigned long, or unsigned long
    > long. I've never heard of an exception. So actually, he's saying something
    > true, but he's talking about something other than what I'm talking about. If
    > I understand this, I can get somewhere. If I don't, I'm going to spend a
    > lot of time telling him that he's wrong, which he's not going to believe,
    > because he's tested his claim and it's obviously true.


    You raise a point that I had mostly ignored: size_t could be a typedef
    for something other than one of the five predefined unsigned integer
    types (you forgot unsigned char). In particular, it could be a typedef
    for one of the extended unsigned integer types. (C99 only; C90 didn't
    have extended integer types.)

    (Note that the description of the 'z' modifier for fprintf implicitly
    assumes that a size_t argument is not promoted, and therefore that
    size_t is not unsigned short or unsigned char. Note also that a
    strict reading implies that size_t cannot be a typedef for plain
    char, even if char happens to be unsigned, because char is not
    one of the "unsigned integer types", even if it's an integer type
    that's unsigned. I'd be astonished if either of these mattered
    for any real-world implementation.)

    So saying that size_t is the same as one of the standard unsigned
    integer types is imprecise. But saying that size_t is the same as one
    of the "unsigned integer types" (as that term is defined in C99
    6.2.5p6) is both precise and correct.

    C99 6.7.7p3:
    A typedef declaration does not introduce a new type, only a synonym
    for the type so specified.
    That's about as clear as it can be.

    The title of 6.7.7 is "Type definitions". The introductory subsections
    for several standard headers refer to types (such as size_t) being
    "defined". The only consistent conclusion is that "defining" a type
    does not "introduce" (or create) a new type.

    Thus my position, that size_t is not a distinct type, but is the same
    type as one of the unsigned integer types. And this is on the level of
    the abstract language spec, *not* with respect to any particular
    implementation. The choice of which unsigned integer type size_t is the
    same type as is implementation-specific. The fact that it's the same as
    one of them is not.

    > Once we've got that figured out, we can potentially have a productive
    > discussion about whether it's more useful or effective to think about types
    > in terms of logical types or in terms of the compatibility rules that
    > are invoked when you try to assign a 'foo *' to a 'bar *'. Both ways of
    > thinking about types work. You can write large programs thinking about
    > it either way. Furthermore, each way of thinking about types will expose
    > you to some problems -- which the other avoids.


    I understand that you think of size_t as a distinct type. I agree 100%
    that it's useful to think of size_t as a distinct *something*. The
    point where I disagree is the use of the word "type" to describe it.

    Yes, if I program *as if* size_t were an additional predefined
    integer type, distinct from all others, that's likely to lead me
    to write good and/or portable code. (Similarly, I tend to pretend
    that compound statements require braces, even though of course
    they don't.) And the "size_t is a distinct type" model is simpler
    than the "size_t is the same as one of the unsigned integer types,
    but which one it is depends on the implementation, and writing code
    as if it were a distinct type is likely to lead to better results"
    model. It's just that the latter model is correct -- assuming
    that I use the word "type" the same way the standard does.

    > The same thing comes up when, say, someone talks about "the stack". All
    > the experienced C programmers know that C doesn't have a stack, except the
    > ones who know that C does have a stack. There are at least three reasonably
    > plausible ways of thinking about this. You can treat it as a contiguous
    > block of memory which always grows in the same direction. Sure, it's not
    > exactly right, but it'll work well enough most of the time, and it's simple.
    > You can treat it as totally separate activation records. You can think of
    > it more like a LIFO queue, without any regard to how it goes together.
    >
    > All of these models *work*. None of them are exactly mandated. If, instead
    > of calling people "wrong" when they use a different model, you try to
    > understand the model they're using and see how it could be useful to you,
    > you're more likely to learn something.


    On the other hand, assuming the contiguous block of memory model can
    lead to errors. For example, you might assume that comparisons of
    addresses between different function calls (perhaps logged with
    fprintf(log_file, "%p", ...)) tells you something about the calling
    sequence. (And on most implementations, it does.)

    On the other other hand, it's certainly possible to have a mental
    model of "the stack" as a contiguous block of memory that always
    grows in a consistent direction and still write good and portable
    code. But it requires avoiding depending on some of the implications
    of that model. Personally, I prefer to use a mental model that,
    though it might be more complex and/or abstract, doesn't make me
    keep track of which implications I can actually depend on and which
    I can't. In addition, the rule that you can't compare pointers to
    distinct objects with <, <=, >, or >= seems a lot less arbitrary.

    (And as usual, that was a lot longer than I thought it would be.)

    > Learning to distinguish between the thing you're modeling, and your model
    > of it, is really useful. It can make you a better programmer. It can
    > also reduce, dramatically, the number of clueless jerks you encounter on
    > Usenet.
    >
    > -s


    --
    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, Oct 23, 2010
    #3
  4. Seebs

    Seebs Guest

    On 2010-10-23, Keith Thompson <> wrote:
    > Of course I can't resist the urge to quibble with some of the details
    > even in this post. :cool:}


    Of course! :)

    > You raise a point that I had mostly ignored: size_t could be a typedef
    > for something other than one of the five predefined unsigned integer
    > types (you forgot unsigned char). In particular, it could be a typedef
    > for one of the extended unsigned integer types. (C99 only; C90 didn't
    > have extended integer types.)


    Right.

    > So saying that size_t is the same as one of the standard unsigned
    > integer types is imprecise. But saying that size_t is the same as one
    > of the "unsigned integer types" (as that term is defined in C99
    > 6.2.5p6) is both precise and correct.


    Yes.

    However, I'm not sure it's *useful* -- so far as I can tell, any program
    which is correct only if that is true is logically incorrect.

    > C99 6.7.7p3:
    > A typedef declaration does not introduce a new type, only a synonym
    > for the type so specified.
    > That's about as clear as it can be.


    Yes. I think the problem is that the word "type" is used in two different
    ways in the standard; sometimes to refer to the underlying thing that has
    to be compatible, sometimes to the relation between a name and that thing.

    > The title of 6.7.7 is "Type definitions". The introductory subsections
    > for several standard headers refer to types (such as size_t) being
    > "defined". The only consistent conclusion is that "defining" a type
    > does not "introduce" (or create) a new type.


    I'm inclined to agree.

    > Thus my position, that size_t is not a distinct type, but is the same
    > type as one of the unsigned integer types. And this is on the level of
    > the abstract language spec, *not* with respect to any particular
    > implementation. The choice of which unsigned integer type size_t is the
    > same type as is implementation-specific. The fact that it's the same as
    > one of them is not.


    Yup. But there's no specific type it's necessarily the same as, and it's
    possible (though unheard of) for an implementation to have no other visible
    type which is the same as it.

    Huh. Actually, that leads to an interesting question.

    We already know that "long" and "int" can be distinct types even when they
    have the same representation.

    Imagine, if you will, an implementation which creates a new type:
    __SIZE_T
    which is a 32-bit unsigned integer type which is distinct from unsigned long,
    but which is an extended unsigned integer type.

    So far as I can tell, it's fine for size_t to then be a typedef for __SIZE_T,
    which is incompatible with EVERY other type.

    > I understand that you think of size_t as a distinct type. I agree 100%
    > that it's useful to think of size_t as a distinct *something*. The
    > point where I disagree is the use of the word "type" to describe it.


    I think it'd be a lot easier to work on that if the language had better
    language for the distinction between the things which are defined by
    <stddef.h> and the things which are created when you create a new struct
    type.

    > Yes, if I program *as if* size_t were an additional predefined
    > integer type, distinct from all others, that's likely to lead me
    > to write good and/or portable code. (Similarly, I tend to pretend
    > that compound statements require braces, even though of course
    > they don't.) And the "size_t is a distinct type" model is simpler
    > than the "size_t is the same as one of the unsigned integer types,
    > but which one it is depends on the implementation, and writing code
    > as if it were a distinct type is likely to lead to better results"
    > model. It's just that the latter model is correct -- assuming
    > that I use the word "type" the same way the standard does.


    Well, the same way the standard does sometimes. I think mine is correct
    if you use "type" the way it's used in the description of <stddef.h>.
    And that's really the problem -- we seem to have two quite clearly
    incompatible usages. I suppose in theory this is a defect. It's mostly
    a harmless one, though -- this is the first time I've ever seen it come
    up.

    More interestingly, so far as I can tell, there's not a single case on the
    table of either way of talking about types creating a problem for an actual
    user thinking about or writing in C. They're incompatible with each others'
    premises and terminology, but each seems to be internally consistent and
    consistent with at least some of the usage in the standard.

    > (And as usual, that was a lot longer than I thought it would be.)


    But informative.

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
    Seebs, Oct 23, 2010
    #4
  5. Seebs

    Seebs Guest

    Re: Talking about talking about C.

    On 2010-10-23, MartinBroadhurst <> wrote:
    > On 23 Oct, 19:44, Seebs <> wrote:
    >> Here's an example of how I might apply that. ?It is obvious to me that size_t
    >> is distinct from any of the standard unsigned integer types.


    > No, no! It's distinct from *all but one* of the standard unsigned
    > integer types.


    It could be distinct from all of them -- it could be an extended unsigned
    integer type.

    However, I think you're missing the point of what I'm saying. Consider
    that I almost certainly understand how typedef works and so on -- I spend
    a decade on the ISO C committee. You might, then, reasonably conclude
    that, especially after spending a couple of days arguing about this very
    point and citing the standard, I *probably* actually understand it.

    So what on earth is happening when I make this statement which appears to
    be false? Presumably, I must be trying to express something different.

    And that is this: Even if we know, for sure, that some header somewhere
    says:
    typedef unsigned long size_t;
    it is still possible, and useful, to distinguish between "size_t" and
    "unsigned long". It is better to write:
    printf("%zu\n", sizeof(x));
    than
    printf("%lu\n", sizeof(x));

    Why? Because, even though it is true that size_t is almost certainly*
    defined in terms of some other type, it is *logically* distinct, and treating
    it as though it were completely distinct will almost inevitably produce
    better code than treating it as though it were not completely distinct.

    -s
    [*] Actually, on thinking about it, I am not sure this is the case. So
    far as I can tell, an implementation is permitted to have size_t itself
    *be* the extended unsigned integer type, at which point, it's not an alias
    for anything. I certainly can't conceive of a strictly conforming
    program which could show such an implementation to be in error.
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
    Seebs, Oct 23, 2010
    #5
  6. Seebs

    Seebs Guest

    Re: Talking about talking about C.

    On 2010-10-24, pete <> wrote:
    > Seebs wrote:
    >> On 2010-10-23, MartinBroadhurst <> wrote:
    >>> On 23 Oct, 19:44, Seebs <> wrote:
    >>>> Here's an example of how I might apply that. ?It is obvious to me that size_t
    >>>> is distinct from any of the standard unsigned integer types.


    >>> No, no! It's distinct from *all but one* of the standard unsigned
    >>> integer types.


    >> It could be distinct from all of them -- it could be an extended unsigned
    >> integer type.


    > You just made that up.


    Nope!

    > The standard says that size_t is
    > "the unsigned integer type of the result of the sizeof operator".


    Yes indeedy.

    But "unsigned integer type" includes two subcategories:

    * standard unsigned integer types (short, int, long, etc.)
    * extended unsigned integer types (???)

    See 6.2.5 (Types), paragraphs 4 and 6. The standard allows you to have
    more integer types than are denoted by the usual range from unsigned char
    to unsigned long long. While this doesn't come up very often, it might
    make sense for an implementation to, say, use the common 8/16/32/64 types
    for the standard unsigned integer types, then also provide at least one
    extended unsigned integer type, such as a 24-bit or 48-bit type.

    An implementor who hated you could in theory use 64 for all the standard
    unsigned integer types except unsigned char, and then have the 16-bit
    and 32-bit types be extended unsigned integer types.

    Re-reading it, though, it seems that the extended types have to use
    identifiers reserved for any use (footnote 28). So it seems to me that
    there must exist some name for that type which is not size_t, so
    size_t has to be an alias for some type, though there may be no way
    for standard code to use that type directly.

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
    Seebs, Oct 24, 2010
    #6
  7. Re: Talking about talking about C.

    Seebs <> writes:
    [...]
    > [*] Actually, on thinking about it, I am not sure this is the case. So
    > far as I can tell, an implementation is permitted to have size_t itself
    > *be* the extended unsigned integer type, at which point, it's not an alias
    > for anything. I certainly can't conceive of a strictly conforming
    > program which could show such an implementation to be in error.


    If size_t is a typedef for an extended unsigned integer type,
    that type has a name which is an implementation-defined keyword
    (or perhaps a sequence of keywords like "unsigned __int32").

    If size_t itself were an extended unsigned integer type, then size_t
    would be a keyword.

    A strictly conforming program can use "size_t" as an identifier,
    for example as the name of an automatic variable.

    --
    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, Oct 24, 2010
    #7
  8. Re: Talking about talking about C.

    Seebs <> writes:
    [...]
    > Re-reading it, though, it seems that the extended types have to use
    > identifiers reserved for any use (footnote 28). So it seems to me that
    > there must exist some name for that type which is not size_t, so
    > size_t has to be an alias for some type, though there may be no way
    > for standard code to use that type directly.


    A conforming program can use the type name directly. (A strictly
    conforming, or even a portable or "clc-compliant" program, cannot.)

    --
    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, Oct 24, 2010
    #8
  9. Seebs

    Seebs Guest

    On 2010-10-24, Keith Thompson <> wrote:
    > Seebs <> writes:
    >> However, I'm not sure it's *useful* -- so far as I can tell, any program
    >> which is correct only if that is true is logically incorrect.


    > Such a program can be non-portable, but it's not necessarily logically
    > incorrect.


    Interesting point!

    > The initialization, which is non-portable, might be intended as a
    > compile-time assertion that size_t is a typedef for unsigned long.
    > Maybe I have a reason to want my program to compile only if that
    > assumption is correct. Maybe it reduces the amount of testing I
    > have to do. Or maybe I just want to see how it compiles as a way
    > of learning more about the implementation I'm using -- which is a
    > perfectly valid goal.


    As a compile-time assertion, that's sort of clever.

    >>> C99 6.7.7p3:
    >>> A typedef declaration does not introduce a new type, only a synonym
    >>> for the type so specified.
    >>> That's about as clear as it can be.


    >> Yes. I think the problem is that the word "type" is used in two different
    >> ways in the standard; sometimes to refer to the underlying thing that has
    >> to be compatible, sometimes to the relation between a name and that thing.


    > Hmmm. I don't think I agree.


    > If a "type" is sometimes, as you say, "the relation between a name and
    > that thing", then in that sense the declarations in <stddef.h> *create*
    > types. But we know that typedefs *don't* create types, because 6.7.7p3
    > says they don't.


    Ahh, but the key here is *sometimes*. My assertion is that 6.7.7 is using
    the word "type" in the sense of "underlying thing", and that the <stddef.h>
    section is using the word "type" in the sense of "relation between name and
    thing".

    Consider that, when you're looking at <stddef.h>, it's irrelevant to you
    whether size_t is the same as any other type or not -- you are only concerned
    with the fact that you can declare things of the type size_t after you
    have included the header. But when you're reading 6.7.7, you're looking
    into the actual underlying question of how typedef works. In that context,
    you *do* need to know about that distinction -- that it is just creating
    a new name for an existing thing.

    > I suspect (of course, correct me if I'm wrong) your reasoning was
    > something like this:


    > 1. <stddef.h> defines types.
    > 2. Defining types means creating types.


    I'm not sure about this. The more I think about it, the more I think that
    "creating" is the wrong interpretation of "defining", and that a whole lot
    of the disputes seem to come from the assertion that to define something is
    to create it.

    > If so, I think step 2 is where you went astray.


    I think it is, at any event, a claim that I'm currently inclined to
    reject.

    >> Yup. But there's no specific type it's necessarily the same as, and it's
    >> possible (though unheard of) for an implementation to have no other visible
    >> type which is the same as it.


    > I'm not sure it is possible. size_t must be an "unsigned integer
    > type" (7.17p2). The "unsigned integer types" are the five "standard
    > unsigned integer types" plus the "extended unsigned integer types"
    > (of which there are zero or more). 6.2.5 doesn't actually say that
    > each of the extended unsigned integer types has a name, but I think
    > it assumes that it does; a footnote on the sentence that introduces
    > extended integer types discusses the form of implementation-defined
    > keywords.


    Yes.

    Thus the qualifier "visible". If the implementation used __SIZE_T_MAGIC
    as the type that size_t is an alias for, there's no way for you to "see"
    that. You can't interact with it, you can't use the name, you can't
    do anything with it. The only *visible* type is size_t.

    >> So far as I can tell, it's fine for size_t to then be a typedef for __SIZE_T,
    >> which is incompatible with EVERY other type.


    > Yes. It's also fine for size_t to be a typedef for unsigned long,
    > which is incompatible with every other type. I don't see that the
    > __SIZE_T case is significantly different.


    The difference is that __SIZE_T is reserved for *all* uses. The
    implementation is free to prohibit you from declaring anything using
    that spelling, so far as I can tell.

    >> I think it'd be a lot easier to work on that if the language had better
    >> language for the distinction between the things which are defined by
    >> <stddef.h> and the things which are created when you create a new struct
    >> type.


    > I think it does; they're called typedefs and structs types,
    > respectively.


    Yeah, "typedef names" is actually pretty useful.

    C would benefit from a way to tag whether the intent is to make an
    incompatible new type or just to have an easier way to spell a type
    without any incompatibilities.

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
    Seebs, Oct 24, 2010
    #9
  10. Seebs

    Seebs Guest

    Re: Talking about talking about C.

    On 2010-10-24, Keith Thompson <> wrote:
    > If size_t is a typedef for an extended unsigned integer type,
    > that type has a name which is an implementation-defined keyword
    > (or perhaps a sequence of keywords like "unsigned __int32").
    >
    > If size_t itself were an extended unsigned integer type, then size_t
    > would be a keyword.
    >
    > A strictly conforming program can use "size_t" as an identifier,
    > for example as the name of an automatic variable.


    Your argument is persuasive, as is the observation that the extended
    types are required to have names that are reserved for any use by
    the implementation.

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
    Seebs, Oct 24, 2010
    #10
  11. Seebs

    Seebs Guest

    Re: Talking about talking about C.

    On 2010-10-24, Keith Thompson <> wrote:
    > Seebs <> writes:
    > [...]
    >> Re-reading it, though, it seems that the extended types have to use
    >> identifiers reserved for any use (footnote 28). So it seems to me that
    >> there must exist some name for that type which is not size_t, so
    >> size_t has to be an alias for some type, though there may be no way
    >> for standard code to use that type directly.


    > A conforming program can use the type name directly. (A strictly
    > conforming, or even a portable or "clc-compliant" program, cannot.)


    I am toying with a notion: Imagine a compiler which has extended types
    which you are NOT allowed to use -- any attempt to declare an object of
    these types gets you compiler errors. And which then has typedef "bless"
    them, so a typedef name pointing at them can be used.

    So far as I can tell, "reserved for any use" would permit this kind of
    silliness.

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
    Seebs, Oct 24, 2010
    #11
  12. Seebs <> writes:
    > On 2010-10-24, Keith Thompson <> wrote:

    [...]
    >> If a "type" is sometimes, as you say, "the relation between a name and
    >> that thing", then in that sense the declarations in <stddef.h> *create*
    >> types. But we know that typedefs *don't* create types, because 6.7.7p3
    >> says they don't.

    >
    > Ahh, but the key here is *sometimes*. My assertion is that 6.7.7 is using
    > the word "type" in the sense of "underlying thing", and that the <stddef.h>
    > section is using the word "type" in the sense of "relation between name and
    > thing".
    >
    > Consider that, when you're looking at <stddef.h>, it's irrelevant to you
    > whether size_t is the same as any other type or not -- you are only concerned
    > with the fact that you can declare things of the type size_t after you
    > have included the header.


    Perhaps, depending on just why I'm looking at it.

    > But when you're reading 6.7.7, you're looking
    > into the actual underlying question of how typedef works. In that context,
    > you *do* need to know about that distinction -- that it is just creating
    > a new name for an existing thing.
    >
    >> I suspect (of course, correct me if I'm wrong) your reasoning was
    >> something like this:

    >
    >> 1. <stddef.h> defines types.
    >> 2. Defining types means creating types.

    >
    > I'm not sure about this. The more I think about it, the more I think that
    > "creating" is the wrong interpretation of "defining", and that a whole lot
    > of the disputes seem to come from the assertion that to define something is
    > to create it.
    >
    >> If so, I think step 2 is where you went astray.

    >
    > I think it is, at any event, a claim that I'm currently inclined to
    > reject.


    Cool.

    Consider also something I mentioned in another thread. Look at the
    definition of "definition" in 6.7p5. It's restricted to object
    definitions, function definitions, enumeration constant (*not*
    enumeration types), and typedef names. Other constructs that
    create new types, such as struct declarations are not "definitions".
    So defining something doesn't mean creating something. (Later I'll
    try to figure out just what the standard really means by "defining"
    something).

    [...]

    >>> So far as I can tell, it's fine for size_t to then be a typedef for __SIZE_T,
    >>> which is incompatible with EVERY other type.

    >
    >> Yes. It's also fine for size_t to be a typedef for unsigned long,
    >> which is incompatible with every other type. I don't see that the
    >> __SIZE_T case is significantly different.

    >
    > The difference is that __SIZE_T is reserved for *all* uses. The
    > implementation is free to prohibit you from declaring anything using
    > that spelling, so far as I can tell.


    Hmm.

    In this hypothetical implementation, the implementation chose
    to reserve the name __SIZE_T as a keyword that's the name
    for an extended integer type. Once it's done that, I'd expect
    (non-portable) programs to be able to use that keyword to refer to
    that same type.

    I suppose the implementation could arbitrarily restrict the use
    of that keyword other than in standard headers; I'm not quite sure
    whether it would be legal for it to do so.

    And I think we're off on a tangent.

    >>> I think it'd be a lot easier to work on that if the language had better
    >>> language for the distinction between the things which are defined by
    >>> <stddef.h> and the things which are created when you create a new struct
    >>> type.

    >
    >> I think it does; they're called typedefs and structs types,
    >> respectively.

    >
    > Yeah, "typedef names" is actually pretty useful.
    >
    > C would benefit from a way to tag whether the intent is to make an
    > incompatible new type or just to have an easier way to spell a type
    > without any incompatibilities.


    Yeah, I think I may have mentioned that a few dozen followups ago. :cool:}

    --
    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, Oct 24, 2010
    #12
  13. Seebs

    Seebs Guest

    On 2010-10-24, Keith Thompson <> wrote:
    > Seebs <> writes:
    >> Consider that, when you're looking at <stddef.h>, it's irrelevant to you
    >> whether size_t is the same as any other type or not -- you are only concerned
    >> with the fact that you can declare things of the type size_t after you
    >> have included the header.


    > Perhaps, depending on just why I'm looking at it.


    I can't immediately think of a purpose for which I'd want to use the
    information that size_t is probably an alias for a standard integer
    type, except maybe for debugging a program which might be making
    a mistake in relying on that in some way.

    > Consider also something I mentioned in another thread. Look at the
    > definition of "definition" in 6.7p5. It's restricted to object
    > definitions, function definitions, enumeration constant (*not*
    > enumeration types), and typedef names. Other constructs that
    > create new types, such as struct declarations are not "definitions".
    > So defining something doesn't mean creating something. (Later I'll
    > try to figure out just what the standard really means by "defining"
    > something).


    My guess:

    For things you generate code for, it's the thing that causes the
    code to be generated.

    For things that are names or words, it's the thing that gives
    meaning to the name or word.

    > In this hypothetical implementation, the implementation chose
    > to reserve the name __SIZE_T as a keyword that's the name
    > for an extended integer type. Once it's done that, I'd expect
    > (non-portable) programs to be able to use that keyword to refer to
    > that same type.


    > I suppose the implementation could arbitrarily restrict the use
    > of that keyword other than in standard headers; I'm not quite sure
    > whether it would be legal for it to do so.


    I'm pretty sure it would. It's reserved!

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
    Seebs, Oct 24, 2010
    #13
  14. Seebs

    Jorgen Grahn Guest

    Mental models (Re: [META] Talking about talking about C.)

    On Sat, 2010-10-23, Keith Thompson wrote:
    > Seebs <> writes:

    ....
    >> The same thing comes up when, say, someone talks about "the stack". All
    >> the experienced C programmers know that C doesn't have a stack, except the
    >> ones who know that C does have a stack. There are at least three reasonably
    >> plausible ways of thinking about this. You can treat it as a contiguous
    >> block of memory which always grows in the same direction. Sure, it's not
    >> exactly right, but it'll work well enough most of the time, and it's simple.
    >> You can treat it as totally separate activation records. You can think of
    >> it more like a LIFO queue, without any regard to how it goes together.

    ....
    > On the other hand, assuming the contiguous block of memory model can
    > lead to errors. For example, you might assume that comparisons of
    > addresses between different function calls (perhaps logged with
    > fprintf(log_file, "%p", ...)) tells you something about the calling
    > sequence. (And on most implementations, it does.)
    >
    > On the other other hand, it's certainly possible to have a mental
    > model of "the stack" as a contiguous block of memory that always
    > grows in a consistent direction and still write good and portable
    > code. But it requires avoiding depending on some of the implications
    > of that model. Personally, I prefer to use a mental model that,
    > though it might be more complex and/or abstract, doesn't make me
    > keep track of which implications I can actually depend on and which
    > I can't.


    My mental model is approximately the Motorola 68000, with an actual
    stack pointer register and everything. But I have never had problems
    grasping that it might look very different ... and invalid code
    doesn't look more right to me just because it fits my MC68000 model;

    unsigned f(unsigned char* p) { return *(unsigned*)p; }

    just looks /wrong/ (to take an example unrelated to stacks).

    I don't think it's just me and my superior mind ;-) -- I think the
    perils of very concrete mental models are exaggerated.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
    Jorgen Grahn, Oct 24, 2010
    #14
  15. Seebs

    Seebs Guest

    Re: Mental models (Re: [META] Talking about talking about C.)

    On 2010-10-24, Jorgen Grahn <> wrote:
    > I don't think it's just me and my superior mind ;-) -- I think the
    > perils of very concrete mental models are exaggerated.


    It varies a lot from person to person. Some people are more likely to
    get "trapped" in a bad mental model, just as some people have a harder
    time dropping a bad hypothesis than others.

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
    Seebs, Oct 24, 2010
    #15
  16. superpollo <> writes:
    > Keith Thompson ha scritto:

    [...]
    > what about this?
    >
    > http://cprog.tomsweb.net/cintro.html#2.4
    >
    > "The type char may be equivalent to either signed char or unsigned char
    > (that depends on your compiler), but it is always a separate type from
    > either of these."
    >
    > so what does equivalent mean?


    It means that they have the same size, representation, bounds, and so
    forth.

    --
    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, Oct 24, 2010
    #16
  17. Re: Talking about talking about C.

    Seebs wrote:
    > An implementor who hated you could in theory use 64 for all the standard
    > unsigned integer types except unsigned char, and then have the 16-bit
    > and 32-bit types be extended unsigned integer types.


    Looks like developers of C for CRAY T90 did hate someone:
    http://docs.cray.com/books/004-2179-001/html-004-2179-001/rvc5mrwh.html#QEARLRWH
    ;->

    (Granted, they don't seem to provide 16- and 32-bit types at all.)
    --
    Marcin Grzegorczyk
    Marcin Grzegorczyk, Oct 24, 2010
    #17
  18. Keith Thompson wrote:
    [...]
    > Yes, if I program *as if* size_t were an additional predefined
    > integer type, distinct from all others, that's likely to lead me
    > to write good and/or portable code. (Similarly, I tend to pretend
    > that compound statements require braces, even though of course
    > they don't.)


    You've got me lost here. Braces are in the syntax of a compound
    statement (6.8.2).
    --
    Marcin Grzegorczyk
    Marcin Grzegorczyk, Oct 24, 2010
    #18
  19. Marcin Grzegorczyk <> writes:
    > Keith Thompson wrote:
    > [...]
    >> Yes, if I program *as if* size_t were an additional predefined
    >> integer type, distinct from all others, that's likely to lead me
    >> to write good and/or portable code. (Similarly, I tend to pretend
    >> that compound statements require braces, even though of course
    >> they don't.)

    >
    > You've got me lost here. Braces are in the syntax of a compound
    > statement (6.8.2).


    Sorry, "compound statement" was the wrong phrase.

    What I really meant was that I tend to pretend that selection and
    iteration statements require braces. For example, I'll write
    if (condition) {
    statement;
    }
    rather than
    if (condition)
    statement;

    To some extent it's a habit I picked up from Perl, which does
    require braces in similar contexts, but it also (IMHO) makes
    maintenance easier.

    But I remain aware that the *language* doesn't require the braces.

    --
    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, Oct 24, 2010
    #19
  20. Seebs

    Seebs Guest

    On 2010-10-24, Marcin Grzegorczyk <> wrote:
    > Keith Thompson wrote:
    > [...]
    >> Yes, if I program *as if* size_t were an additional predefined
    >> integer type, distinct from all others, that's likely to lead me
    >> to write good and/or portable code. (Similarly, I tend to pretend
    >> that compound statements require braces, even though of course
    >> they don't.)


    > You've got me lost here. Braces are in the syntax of a compound
    > statement (6.8.2).


    I think what Keith is referring to is "the body of a control statement".

    e.g.:
    if (foo) {
    bar;
    }

    So really, "as if the body of a control statement had to be a compound
    statement".

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
    Seebs, Oct 24, 2010
    #20
    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. walala
    Replies:
    1
    Views:
    744
    Jonathan Bromley
    Sep 1, 2003
  2. Nym Pseudo

    META NAME and META HTTP-EQUIV

    Nym Pseudo, Sep 26, 2003, in forum: HTML
    Replies:
    1
    Views:
    527
    =?iso-8859-1?Q?brucie?=
    Sep 26, 2003
  3. Duane Johnson

    Meta methods to govern meta data?

    Duane Johnson, Oct 25, 2005, in forum: Ruby
    Replies:
    6
    Views:
    219
    Adam Sanderson
    Oct 28, 2005
  4. Erik Veenstra

    Meta-Meta-Programming

    Erik Veenstra, Feb 7, 2006, in forum: Ruby
    Replies:
    29
    Views:
    348
    Erik Veenstra
    Feb 8, 2006
  5. Erik Veenstra

    Meta-Meta-Programming, revisited

    Erik Veenstra, Jul 21, 2006, in forum: Ruby
    Replies:
    21
    Views:
    419
    Erik Veenstra
    Jul 25, 2006
Loading...

Share This Page