Thread: Declarations

  1. #1
    Caution: Wet Floor
    Join Date
    May 2006
    Posts
    55

    Declarations

    Some of these declarations are bad:

    Code:
    int main() {
    
      char c = 'a';
      int ia[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
      char* sa[3] = {"tic", "tac", "toe"};
    
      char* pc = &c; // ptr to `char'
      int& ir = &ia; // reference to array of ten `int's (?)
      char* psa[] = sa; // ptr to array of character strings (?)
      char** ppc = &pc; // ptr to ptr to `char' (?)
      const *int ci = 5; // ptr to `const int' (?)
      int *const pci = &ci; //`const' ptr to `int' (?)
    }
    I'm having trouble with the items with question marks.

    Output:

    Code:
    decs.cc: In function `int main()':
    decs.cc:8: invalid conversion from `int (*)[10]' to `int'
    decs.cc:8: initialization of non-const reference type `int&' from rvalue of
       type `int (*)[10]'
    decs.cc:9: invalid initializer
    decs.cc:12: syntax error before `int'
    Thanks for your help!

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Code:
    int ia[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    // ...
    int& ir = &ia;
    A variable of type int& is a reference to a single int. You use references like this:
    Code:
    int x;
    int &r = x;
    Initializing a reference to the address of a variable is not usually done (unless it's of type int&* or something), and the type of the variable should match what you're initializing it to. For example, ia is an array, but ir is an int, so that wouldn't work.

    Code:
    char** ppc = &pc;
    pc is of type char*, so &pc is of type char**, so ppc can be initialized to a value like &pc, because they are of the same type.

    Code:
    const *int ci = 5;
    The type of a variable, such as int, must go before any asterisks (*) or ampersands (&). const can go in both places, but it means different things on different sides of asterisks or whatever.

    In addition, a pointer should be initialized to an address, not an integer literal like 5.

    So what's the difference between these two declarations of p, q, and r?
    Code:
    int x = 3;
    
    // the following declarations of p are equivalent
    const int *p = &x;
    int const *p = &x;
    
    int *const q = &x;
    
    // sort of a combination of p and q
    const int *const r = &x;
    When the const is part of the variable's type, e.g. to the left of all asterisks (like p), it means that the value stored in the variable referenced by the pointer cannot be modified. The pointer points to a const int, if you will.

    When the const is after an asterisk (e.g. q), it affects that asterisk. The value in the pointer cannot be changed -- the pointer cannot be re-assigned to point to another variable. However, the value of the variable that the pointer points to can be modified. So the pointer can't point to something else, but it can change what it points to.

    As a final example, the invalid statements in the following code are highlighted in red.
    Code:
    int x = 3;
    const int cx = 3;
    
    const int *cp = &cx;
    cp = &x;  // reassignment of the pointer
    *cp = 4;  // modification of the variable's value
    
    int *const pc = &x;
    pc = &cx;  // reassignment of the pointer to a constant variable
    pc = &x;  // reassignment of the pointer
    *pc = 4;  // modification of the variable's value
    
    const int *cpc = &cx;
    cpc = &x;  // reassignment of the pointer
    *cpc = 4;  // modification of the variable's value
    That's probably just confusing . . . if you search around, you'll find more information on the topic. There are other issues as well, like constant pointers to pointers . . . .
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Registered User
    Join Date
    Dec 2005
    Posts
    54
    char* pc = &c; // ptr to `char'
    char* pc = (char*)c; c is a single character, you are trying to set it equal to an array of characters. a type cast should fix this one.

    int& ir = &ia; // reference to array of ten `int's (?)
    you are trying to set a single int reference to a list of 10 ints. you would need to make an array of references.

    char* psa[] = sa; // ptr to array of character strings (?)
    not to sure on this one

    char** ppc = &pc; // ptr to ptr to `char' (?)


    const *int ci = 5; // ptr to `const int' (?)
    You are trying to tell it to point to a non object. I can't remember exactly how '5' is handled, but that is what you should look up if you want more info.

    int *const pci = &ci; //`const' ptr to `int' (?)

    const int*
    int *const

    I think the problem is that those are not considered the same type. Might take some casting tricks.

    Sorry, probably not the most helpful, been a while since I worked with pointers.

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by JeremyCAFE View Post
    char* pc = &c; // ptr to `char'
    char* pc = (char*)c; c is a single character, you are trying to set it equal to an array of characters. a type cast should fix this one.
    That's legal. No cast needed.

    char* psa[] = sa; // ptr to array of character strings (?)
    not to sure on this one
    Code:
    char* psa[] = sa;
    char* sa[3] = {"tic", "tac", "toe"};
    sa = char*[3], while psa = char*[1] (so to speak). Types are incompatible, because psa contains 3 pointers pointing to 3 strings. You need to redeclare your type (use more pointers) or choose one string to point to.

    char** ppc = &pc; // ptr to ptr to `char' (?)
    Valid.

    const *int ci = 5; // ptr to `const int' (?)
    You are trying to tell it to point to a non object. I can't remember exactly how '5' is handled, but that is what you should look up if you want more info.
    Not only that, but you can't just assign a numeric value to a pointer without a cast (except for NULL). In general, a very bad idea, so don't do that.

    int *const pci = &ci; //`const' ptr to `int' (?)

    const int*
    int *const

    I think the problem is that those are not considered the same type. Might take some casting tricks.
    You are correct - they are not the same type..
    const int* and int* const are not the same and it's unsafe to cast between the two as well.

  5. #5
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    const int* and int* const are not the same and it's unsafe to cast between the two as well.
    It's unsafe to cast between the types if you have no background about what's stored in them -- but you can easily concoct a situation where it's valid:
    Code:
    int x = 3;
    const int *p = &x;
    int *const q = static_cast<int *const>(p);
    *q = 4;
    That's the trouble with casts. When you use a cast, you're telling the compiler that you know more about the situation than it does. Sometimes, you do. But it can backfire on you very easily, because if you change something later the compiler won't help you fix it, because you're still telling it you know better.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Yes, I know, but I don't consider removing or adding const to a variable as safe practice. When you're getting a variable of type const, any const type, it means you aren't supposed to change what the pointer points to or not supposed to change the contents of what it points to.

    So, I might just change that to "generally" unsafe. If it's const, then it's const, deal with it. If it shouldn't be const, then don't declare it as const. If you have to cast your pointers from const, then you have an implentation problem.

  7. #7
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    You can't cast away constness with static_cast.

    Also:
    Code:
    char* sa[3] = {"tic", "tac", "toe"};
    It is legal to assign string literals to non-const char*, but only for backward compatibility reasons. You should never do it. Make it const char* sa[3].
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  8. #8
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    You can't cast away constness with static_cast.
    Yes, of course, that's one of the nice things about C++ casting (compared with C casting). I meant to use const_cast.

    It is legal to assign string literals to non-const char*, but only for backward compatibility reasons. You should never do it. Make it const char* sa[3].
    It's strange . . . in C++ I get a warning, but with the same code compiled as C, not a peep from GCC. I thought string literals were constant in C as well as C++ . . . .
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    C allows you to do some pretty nasty and stupid stuff -_-
    Luckily, C++ stops you right there. But some nasty stuff is still possible like char* p = "my string";

  10. #10
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    But if string literals are constant in both languages, and g++ warns me, then GCC should too. At least I would have thought so. I used -W -Wall -ansi -pedantic for both.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Dunno, are they?
    VC's compiler complains for some things in C++, but not C, even though it's the same code.

  12. #12
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Well, GCC complains about
    Code:
    "string"[3] = 0;
    as expected:
    Code:
    constchar.c:4: error: assignment of read-only location
    But it has no qualms with
    Code:
    char *string = "string";
    string[3] = 0;
    I just thought it was strange . . . .
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    In VC, both statements compile fine in C, but the first fails in C++.
    Though I can see how the second compiles fine.
    So you're basically assigning an address to the pointer and using it as a pointer (non-const) which is completely legal.

  14. #14
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    So you're basically assigning an address to the pointer
    A constant address. That's where I would expect it to choke. Apparently not.

    Strange indeed. From http://publib.boulder.ibm.com/infoce...as400clr39.htm:
    A string literal with the prefix L is a wide string literal. A string literal without the prefix L is an ordinary or narrow string literal.

    C: The type of a narrow string literal is array of char and the type of a wide string literal is array of wchar_t.

    C++: The type of a narrow string literal is array of const char and the type of a wide string literal is array of const wchar_t. Both types have static storage duration.
    If a string literal is of type char* and not const char* in C, why does GCC give an error with this?
    Code:
    "string"[3] = 0;
    It's an error, not a warning, even with no extra parameters passed to GCC.

    [edit] http://www.thescripts.com/forum/thread218632.html [/edit]
    Last edited by dwks; 12-01-2007 at 05:08 PM.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Does gcc hate Forward declarations?
    By SevenThunders in forum C++ Programming
    Replies: 12
    Last Post: 03-16-2009, 02:03 PM
  2. mixing code with declarations
    By robwhit in forum C Programming
    Replies: 12
    Last Post: 01-31-2008, 12:55 AM
  3. Weird function declarations
    By confuted in forum C Programming
    Replies: 6
    Last Post: 11-09-2005, 03:06 PM
  4. help on declarations
    By robasc in forum C Programming
    Replies: 9
    Last Post: 03-05-2005, 01:50 PM
  5. Complex declarations & ?error in Kernighan/Ritchie?
    By zzzaaahhh in forum C Programming
    Replies: 6
    Last Post: 10-04-2004, 04:24 PM