Question on Data Type Declarations

Discussion in 'C Programming' started by phaedrus, Nov 6, 2009.

  1. phaedrus

    phaedrus Guest

    Hi guys,

    Clue me up, please.

    When we declare variables like

    float x;
    int y;
    char z;
    long w;

    and so on, are we doing anything more than just reserving a certain
    number of bytes for these data types to occupy?
    I mean, the compiler doesn't flag up an error if we try to store (for
    example) a letter 'a' in an int, does it? Presumably we can store
    *any* type of data in *any* variable type provided said declared type
    has enough room to accommodate it?
    Aren't the names 'float', 'int', 'char' and so forth simply there to
    remind the programmer what data type the variable should be? The
    compiler is blind to this human distinction, isn't it?
     
    phaedrus, Nov 6, 2009
    #1
    1. Advertising

  2. phaedrus

    Seebs Guest

    On 2009-11-06, phaedrus <> wrote:
    > Clue me up, please.


    What you ask may be possible.

    > When we declare variables like


    > float x;
    > int y;
    > char z;
    > long w;


    > and so on, are we doing anything more than just reserving a certain
    > number of bytes for these data types to occupy?


    Yes.

    We are reserving space and specifying how that space is to be interpreted.

    > I mean, the compiler doesn't flag up an error if we try to store (for
    > example) a letter 'a' in an int, does it?


    No. But that's because:
    1. 'a' is a constant of type int to begin with.
    2. Even if you get the character (say, referring to "a"[0]), it's still got
    an integral-type value.

    > Presumably we can store
    > *any* type of data in *any* variable type provided said declared type
    > has enough room to accommodate it?


    Nope.

    > Aren't the names 'float', 'int', 'char' and so forth simply there to
    > remind the programmer what data type the variable should be? The
    > compiler is blind to this human distinction, isn't it?


    Not in the least.

    What might throw you off is that the compiler will, in many cases,
    automatically perform the given conversion.

    Consider:
    #include <stdio.h>

    int main(void) {
    float f = 3.14;
    int i;
    i = f;
    f = i;
    printf("%f\n", f);
    return 0;
    }

    This, on my system (where sizeof(float) happens to == sizeof(int)), prints
    "3.000000". No warnings, no errors.

    When f is assigned to i, the compiler automatically converts the float to
    an int. When i is assigned back to f, the compiler automatically converts
    back. But converting float to int truncates -- it drops fractional parts.

    This can happen the other way, too:

    #include <stdio.h>

    int main(void) {
    int i = 67108865;
    float f;
    f = i;
    i = f;
    printf("%d\n", i);
    return 0;
    }

    On my system, this yields 67108864.

    Perfectly reasonable, etcetera.

    So, no. It's not just amount of storage; it's also representation that is
    defined.

    -s
    --
    Copyright 2009, 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!
     
    Seebs, Nov 6, 2009
    #2
    1. Advertising

  3. phaedrus

    phaedrus Guest

    On Nov 6, 1:26 pm, Seebs <> wrote:
    > On 2009-11-06, phaedrus <> wrote:
    >
    > > Clue me up, please.

    >
    > What you ask may be possible.
    >

    I consider myself duly clued! THanks!
     
    phaedrus, Nov 6, 2009
    #3
  4. phaedrus

    Seebs Guest

    On 2009-11-06, phaedrus <> wrote:
    > I consider myself duly clued! THanks!


    You didn't insult anyone, and you didn't make up an even less likely claim
    and defend it to the last. I think they'll yank your Usenet license.

    Seriously, though, interesting question; it wouldn't have occurred to me,
    but it was interesting to think about.

    -s
    --
    Copyright 2009, 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!
     
    Seebs, Nov 6, 2009
    #4
  5. Seebs <> writes:
    > On 2009-11-06, phaedrus <> wrote:
    >> Clue me up, please.

    >
    > What you ask may be possible.
    >
    >> When we declare variables like

    >
    >> float x;
    >> int y;
    >> char z;
    >> long w;

    >
    >> and so on, are we doing anything more than just reserving a certain
    >> number of bytes for these data types to occupy?

    >
    > Yes.
    >
    > We are reserving space and specifying how that space is to be interpreted.
    >
    >> I mean, the compiler doesn't flag up an error if we try to store (for
    >> example) a letter 'a' in an int, does it?

    >
    > No. But that's because:
    > 1. 'a' is a constant of type int to begin with.
    > 2. Even if you get the character (say, referring to "a"[0]), it's still got
    > an integral-type value.
    >
    >> Presumably we can store
    >> *any* type of data in *any* variable type provided said declared type
    >> has enough room to accommodate it?

    >
    > Nope.
    >
    >> Aren't the names 'float', 'int', 'char' and so forth simply there to
    >> remind the programmer what data type the variable should be? The
    >> compiler is blind to this human distinction, isn't it?

    >
    > Not in the least.
    >
    > What might throw you off is that the compiler will, in many cases,
    > automatically perform the given conversion.

    [snip]

    On the other hand, in many cases there is no implicit conversion,
    and the compiler will reject any attempt to perform an assignment.
    (Well, actually it's only required to issue a diagnostic, but that
    should tell you to reject it yourself if the compiler isn't kind
    enough to do it for you.)

    All the examples you used (float, int, char, long) are numeric types,
    and any numeric type can be implicitly converted to any other numeric
    type.

    Try compiling this:

    #include <stddef.h>
    int main(void)
    {
    double d = 0.0;
    int *p = NULL;
    struct { int x; int y; } s = { 0, 0 };

    d = 42; /* ok, implicit conversion of int to double */
    p = 42; /* invalid, can't convert int to pointer (unless it's
    a null pointer constant. */
    s = 42; /* complete nonsense; you can't convert *anything* to a
    struct type unless it's already of the same type */
    return 0;
    }

    --
    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, Nov 7, 2009
    #5
  6. phaedrus

    phaedrus Guest

    On Nov 6, 7:57 pm, Keith Thompson <> wrote:

    >All the examples you used (float, int, char, long) are numeric types


    Er, hang on. I'm obviously still not completely clued-up here. You say
    the type 'char' is numeric?? Float, int and long are obviously
    numeric, but char is obviously a single character like 'a' or 'b' or
    'c' for example. A char, though capable of storing up to 0xFF of
    values, is still just an alphabetical character, n'est pas?
     
    phaedrus, Nov 7, 2009
    #6
  7. phaedrus

    Nick Guest

    phaedrus <> writes:

    > On Nov 6, 7:57 pm, Keith Thompson <> wrote:
    >
    >>All the examples you used (float, int, char, long) are numeric types

    >
    > Er, hang on. I'm obviously still not completely clued-up here. You say
    > the type 'char' is numeric?? Float, int and long are obviously
    > numeric, but char is obviously a single character like 'a' or 'b' or
    > 'c' for example. A char, though capable of storing up to 0xFF of
    > values, is still just an alphabetical character, n'est pas?


    Yes. It is confusing, but in C all a char is is a particular sort of
    small integer, and the single quotes around a character are just a way
    of saying "the integer that represents that character in the character
    set being used during compilation".

    On an ASCII machine:
    char a = 65;
    and
    int a = 'A';

    both result in an integer variable (as distinct from an "int") holding
    the same value.
    --
    Online waterways route planner: http://canalplan.org.uk
    development version: http://canalplan.eu
     
    Nick, Nov 7, 2009
    #7
  8. phaedrus <> writes:

    > On Nov 6, 7:57 pm, Keith Thompson <> wrote:
    >
    >>All the examples you used (float, int, char, long) are numeric types

    >
    > Er, hang on. I'm obviously still not completely clued-up here. You say
    > the type 'char' is numeric?? Float, int and long are obviously
    > numeric, but char is obviously a single character like 'a' or 'b' or
    > 'c' for example. A char, though capable of storing up to 0xFF of
    > values, is still just an alphabetical character, n'est pas?


    Non, mon amie. The name is confusing you. signed char and unsigned
    char are simply two of C's integers types. Because characters in old
    encodings like ASCII are all small numbers, char objects can be used
    to hold them; but there are characters that C programmers need to
    manipulate that don't fit in a char object, and char objects can be
    used to manipulate things that aren't characters.

    If I were manipulating pixels, I might use:

    typedef unsigned char pixel[3];
    pixel p = {128, 128, 128};

    and do arithmetic on the components as with any other integer type:
    p[2] = (p[0] + p[1]) / 2; and so on. Nowadays, I'd probably consider
    using one of C99's size-specific types like uint_least8_t or
    uint_fast8_t but that is a whole other issue.

    On the other size, C provides wchar_t -- yet another integer type --
    to hold characters that don't fit into a char.

    There is no way to write "the letter A" in C simply because there is
    no universal agreement about what number should be used to represent
    an A. In C, 'A' is just an integer constant, and while it will be the
    correct number to represent an A on the machine the C compiler is for,
    the resulting code may not work if it is processing data coming from a
    machine that has some other idea about the letter A.

    --
    Ben.
     
    Ben Bacarisse, Nov 7, 2009
    #8
  9. phaedrus

    phaedrus Guest

    OK, all understood.

    I'm not exactly a C noobie, btw. I'm just very rusty and trying to get
    up to speed again. I was actually posting here some 15 years ago and
    always remember this group had one of the best signal/noise ratios of
    any I've ever seen and a extraordinarily erudite contributorship, and
    not just in computer matters. I recognize some familiar names from the
    past. Nice to see this group has survived all those years without too
    much spam and personal attacks blighting it. Well done, chaps.
     
    phaedrus, Nov 7, 2009
    #9
  10. Seebs <> writes:

    > On 2009-11-07, phaedrus <> wrote:
    >> On Nov 6, 7:57 pm, Keith Thompson <> wrote:
    >>>All the examples you used (float, int, char, long) are numeric types

    >
    >> Er, hang on. I'm obviously still not completely clued-up here. You say
    >> the type 'char' is numeric?? Float, int and long are obviously
    >> numeric, but char is obviously a single character like 'a' or 'b' or
    >> 'c' for example. A char, though capable of storing up to 0xFF of
    >> values, is still just an alphabetical character, n'est pas?

    >
    > No. It's a small (CHAR_BIT bits) integer.
    >
    > As it happens, that's sufficient to represent characters on most systems,
    > but it's actually just another integer type. It's in no way special or
    > different because of the use to represent characters.


    But it is special! What other integer type has the property that
    (T)-1 < 0 varies from implementation to implementation?

    Whether char is special in the regard "because of the use to represent
    characters" is certainly debatable, but I think a case can be that
    char is different for exactly this reason. The fact that the
    signedness of char is up to the compiler is a serious obstacle to
    treating it as "just another integer type".

    --
    Ben.
     
    Ben Bacarisse, Nov 8, 2009
    #10
  11. phaedrus

    Bruce Cook Guest

    phaedrus wrote:

    > Hi guys,
    >
    > Clue me up, please.
    >
    > When we declare variables like
    >
    > float x;
    > int y;
    > char z;
    > long w;
    >
    > and so on, are we doing anything more than just reserving a certain
    > number of bytes for these data types to occupy?


    yes this is correct.

    > I mean, the compiler doesn't flag up an error if we try to store (for
    > example) a letter 'a' in an int, does it? Presumably we can store
    > *any* type of data in *any* variable type provided said declared type
    > has enough room to accommodate it?
    > Aren't the names 'float', 'int', 'char' and so forth simply there to
    > remind the programmer what data type the variable should be?


    yes, although the type provides hints to the compiler about how to treat
    operations on that variable.

    As mentioned by other posters, the compiler will automatically translate
    between numeric types (such as float and int) but it will also provide
    warnings for things that we know are going to cause issues (assignment
    between int and pointer types and mis-matched pointer types).

    In the days before C89 most compilers would happily let you commit a
    multitude of sins without warning because the compiler indeed treated
    variables are places to store stuff - the big one being that pointers were
    considered ints so code like this compiled and ran without errors:

    void foo(a)
    int a; /* before c89 we did it this way :) */
    {
    printf("%s", a);
    }

    foo("a trick that bit a lot of people");

    This sort of thing caused massive problems with portability & floating
    pointers that were quite hard to debug.

    In the late '80s compilers such as GCC started to enforce stronger typing
    which improved everyone's life no end and as the standards have evolved
    stronger typing has been added.

    If you want to commit sins these days you have to abuse the casting system:

    double x;
    *(int *)&x= 4;

    Will place an integer into your double storage - and you will rot in hell
    for all eternity.

    (I have seen variations on this used to pass multiple ints around in double
    or long variables - made for a bucket of fun when porting)

    While you *may* know what your compiler is doing in the way it stores data,
    you cannot assume that it will hold for other compilers, or even a later
    version of the same compiler. A lot of us had to learn this the hard way in
    the early days, particularly with the int/pointer assignment assumption.

    Bruce
     
    Bruce Cook, Nov 8, 2009
    #11
  12. phaedrus

    Bruce Cook Guest

    phaedrus wrote:

    > On Nov 6, 7:57 pm, Keith Thompson <> wrote:
    >
    >>All the examples you used (float, int, char, long) are numeric types

    >
    > Er, hang on. I'm obviously still not completely clued-up here. You say
    > the type 'char' is numeric?? Float, int and long are obviously
    > numeric, but char is obviously a single character like 'a' or 'b' or
    > 'c' for example. A char, though capable of storing up to 0xFF of
    > values, is still just an alphabetical character, n'est pas?


    (I'm sure the guys wielding the standards will give exact wording of the
    standard for this)

    in C a char is a character sized int (these days usually a Byte).

    char c; /* on x86 declares an Byte sized int. */
    char c[80]; /* on x86 declares an array of 80 byte sized ints. */

    c= 0x41; /* assigns the value of 41 hex to c - happens to also
    be the ASCII code for the character A */
    print ("%c %x", c, c); /* output: A 41 */

    c= 'A'; /* assigns the integer value of the character code for
    A into c (on x86 this is the ascii value 0x41 */

    It is for this reason that C has no asc() or char() functions - they're
    simply not required.

    Bruce
     
    Bruce Cook, Nov 8, 2009
    #12
  13. Bruce Cook <> writes:
    > phaedrus wrote:
    >> Clue me up, please.
    >>
    >> When we declare variables like
    >>
    >> float x;
    >> int y;
    >> char z;
    >> long w;
    >>
    >> and so on, are we doing anything more than just reserving a certain
    >> number of bytes for these data types to occupy?

    >
    > yes this is correct.
    >
    >> I mean, the compiler doesn't flag up an error if we try to store (for
    >> example) a letter 'a' in an int, does it? Presumably we can store
    >> *any* type of data in *any* variable type provided said declared type
    >> has enough room to accommodate it?
    >> Aren't the names 'float', 'int', 'char' and so forth simply there to
    >> remind the programmer what data type the variable should be?

    >
    > yes, although the type provides hints to the compiler about how to treat
    > operations on that variable.


    No, declaring "float x;" does much more than just telling the compiler
    that x should occupy sizeof(float) bytes. It affects every operation
    that you can perform on x. It doesn't just provide hints; it provides
    information that the compiler is obligated to pay close attention to.

    To put it another way, the number of bytes occupied by x is just one
    of the things that "float x;" tells the compiler, and it's not
    particularly the most important one.

    > As mentioned by other posters, the compiler will automatically translate


    "Convert" is more accurate than "translate".

    > between numeric types (such as float and int) but it will also provide
    > warnings for things that we know are going to cause issues (assignment
    > between int and pointer types and mis-matched pointer types).


    Providing a warning is the least that a compiler can do. In many
    cases, compilers will print an error message and reject the program.

    > In the days before C89 most compilers would happily let you commit a
    > multitude of sins without warning because the compiler indeed treated
    > variables are places to store stuff - the big one being that pointers were
    > considered ints so code like this compiled and ran without errors:
    >
    > void foo(a)
    > int a; /* before c89 we did it this way :) */


    Or the "int a;" could be omitted.

    > {
    > printf("%s", a);
    > }
    >
    > foo("a trick that bit a lot of people");


    Pointers weren't *quite* considered to be integers, but pre-C89
    compilers were generally more lenient about implicit conversions.

    The above code is actually still legal (sort of) in C90 and even C99.
    Its behavior is undefined, but it's likely to print "a trick that bit
    a lot of people" under many implementations.

    Oh, and pre-ANSI C didn't have "void".

    Even in the earliest versions of C, the declaration
    float x;
    would tell the compiler more than just the size of x. For example,
    this:
    x = 42;
    would generate quite different code given "float x;" than given
    "int x;", even if int and float are the same size.

    (I think BCPL, one of C's ancestor languages, was essentially
    typeless.)

    [...]

    --
    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, Nov 8, 2009
    #13
  14. phaedrus

    Seebs Guest

    On 2009-11-08, Keith Thompson <> wrote:
    > Oh, and pre-ANSI C didn't have "void".


    I think some did. There were shreds of some interesting tests in perl
    back then, and some barely-ANSI or pre-ANSI compilers definitely had,
    say, void, but not support for prototypes. Or partial support for void.
    I seem to recall that there were some that handled "void foo()", and a
    few that knew about "void *".

    But it wasn't exactly a standard or stable feature.

    I mostly got interested in this at a time when the ANSI standard existed
    and the compilers I mostly used were at least largely ANSI-like, but I had
    to use a few pre-ANSI compilers sometimes, and some of them still had
    some support for void.

    Hmm.

    I think the three questions were:
    * void return type
    * void arg list (essentially implies prototypes)
    * void *

    Been too long; I'd have to track down 20-year-old copies of the perl source.
    Which I probably have somewhere.

    -s
    --
    Copyright 2009, 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!
     
    Seebs, Nov 8, 2009
    #14
    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. Roger Levy
    Replies:
    20
    Views:
    912
    Neal Gafter
    Jan 5, 2005
  2. jan V
    Replies:
    15
    Views:
    661
    Dale King
    Sep 12, 2005
  3. Wolfgang Meyer
    Replies:
    1
    Views:
    332
    Rob Williscroft
    Apr 24, 2004
  4. Marcus Lessard

    Mangled function type declarations?

    Marcus Lessard, Oct 17, 2003, in forum: C Programming
    Replies:
    1
    Views:
    353
    Eric Sosman
    Oct 17, 2003
  5. Mark 'Kamikaze' Hughes

    Re: does lack of type declarations make Python unsafe?

    Mark 'Kamikaze' Hughes, Jun 29, 2003, in forum: Python
    Replies:
    4
    Views:
    806
    Anton Vredegoor
    Jul 1, 2003
Loading...

Share This Page