Thread: Basic things I need to know

  1. #46
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    constants must be initialized. Your compiler will agree.

    Code:
    $ cat const.cc
    int main()
    {
       const char **x;
       **x = '!'; // dammit
    }
    Owner@pavilion ~
    $ g++ const.cc
    const.cc: In function `int main()':
    const.cc:4: error: assignment of read-only location

  2. #47
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Quote Originally Posted by dwks
    I don't know the exact details, but you can't have a const pointer to a pointer. Perhaps someone can explain why.
    A const pointer to a pointer would be:

    char ** const x;

    Remember the rule with pointers is to read them backwards: "x is a const pointer to a pointer to a char"

    And that does work for me, this code compiles:

    char * y;
    char ** const x = &y;

    In fact all variations compile for me:

    const char ** a; (a pointer to a pointer to a const char)
    char * const * b; (a pointer to a const pointer to a char)
    char **const c; (a const pointer to a pointer to a char)

    const char * const * const d; (a const pointer to a const pointer to a const char)

    But yes, if the pointer is const (as in c and d above), it needs initialization just like any const variable:

    Code:
    	const char x = 'x';
    	const char * const y= &x;
    	const char * const * const z = &y;
    I think what you were thinking of was the following, and one of the ways that a constant pointer and a reference are different:

    char * const * i; // Legal: pointer to const pointer.
    char & * j; // Illegal: pointer to reference
    Last edited by Cat; 10-13-2006 at 05:57 PM.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  3. #48
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Quote Originally Posted by Daved
    Also, I think that x can be initialized later, so your second point is wrong as well.
    No. It can't be initialized later.You try it. Your point is wrong.

    EDIT: Nope. I'm wrong. The pointer is not a constant.
    Last edited by Mario F.; 10-13-2006 at 06:18 PM.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  4. #49
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    My reply is pokey as all hell, but...
    Code:
    #include <iostream>
    using std::cout;
    
    int main(void)
    {
        const char a = '5', c = '*';
        const char *b, *d;
        const char **x;
        b = &a;
        x = &b;
        cout << "&a = " << static_cast<const void*>(&a) << ", "
             << "&b = " << static_cast<const void*>(&b) << ", "
             << "&c = " << static_cast<const void*>(&c) << ", "
             << "&d = " << static_cast<const void*>(&d) << "\n";
        cout << "x = "   << static_cast<const void*>( x) << ", "
             << "*x = "  << static_cast<const void*>(*x) << ", "
             << "**x = '" << **x << "'\n";
        b = &c;
        cout << "x = "   << static_cast<const void*>( x) << ", "
             << "*x = "  << static_cast<const void*>(*x) << ", "
             << "**x = '" << **x << "'\n";
        d = &a;
        x = &d;
        cout << "x = "   << static_cast<const void*>( x) << ", "
             << "*x = "  << static_cast<const void*>(*x) << ", "
             << "**x = '" << **x << "'\n";
        d = &c;
        cout << "x = "   << static_cast<const void*>( x) << ", "
             << "*x = "  << static_cast<const void*>(*x) << ", "
             << "**x = '" << **x << "'\n";
        return 0;
    }
    
    /* my output
    &a = 0022FF77, &b = 0022FF70, &c = 0022FF76, &d = 0022FF6C
    x = 0022FF70, *x = 0022FF77, **x = '5'
    x = 0022FF70, *x = 0022FF76, **x = '*'
    x = 0022FF6C, *x = 0022FF77, **x = '5'
    x = 0022FF6C, *x = 0022FF76, **x = '*'
    */
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  5. #50
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    By the way, here is my solution for the previous problem:

    Code:
    01 void SomeFunction(char * str){
    02 
    03     char * buffer = new char[256];
    04     char * buffer2 = new char[256];
    05 
    06     sprintf(buffer, "The contents of str are: %s",str);
    07     sprintf(buffer2, "Skipping the first 10 characters of str gives: %s", str + 10);
    08 
    09     std::cout << buffer << std::endl << buffer2 << std::endl;
    10 
    11     delete[] buffer;
    12     delete[] buffer2;
    13 }
    First, in general this code suffers from what I call "C++--" -- it's basically C code that masquerades as C++. In fact changing that will solve every problem the code has, but first, the specific things that are wrong:

    Line 1: The parameter is not const-correct; the string is not modified and so it should be const char *.

    Line 4: The new[] can throw an exception. It could on line 3 as well, but actually that doesn't cause a problem. If line 4 throws, the memory allocated successfully on line 3 cannot be deallocated, it's leaked.

    Line 6: This assumes that the total length of the resulting string is less than 256 characters including a trailing NULL. If not: buffer overflow.

    Line 7: This assumes not only the total length of the resulting string is less than 256 chars, but also that the source string is at least 10 characters long.

    Line 9: If the iostream throws an exception when writing to console, both buffer and buffer2 are memory leaks, because memory that was successfully allocated will not be able to be deallocated as the pointers to that memory will be lost.

    Here's a better source code:

    Code:
    void SomeFunction(const std::string & str){
    
        std::string buffer, buffer2;
    
        buffer = "The contents of str are: " + str;
        if (str.length() >= 10)
            buffer2 = "Skipping the first 10 characters of str gives: " + str.substr(10);
        else
            buffer2 = "The string is less than 10 characters long";
    
        std::cout << buffer << std::endl << buffer2 << std::endl;
    
    }
    In this, I could have made the parameter just a normal std::string (which, because it would be passed by copy, would not need to be const), but I chose reference to const as it will avoid constructing a copy if we pass in a std::string variable.

    If we pass in a string literal, it will construct a temporary std::string (which it would NOT do if the reference was not to const). This does take a slight time, but in reality it's virtually identical to the time needed to strlen() a const char * string, so there's no real problem using it.

    Making the buffers string variables instead of character arrays eliminates any worry about overflow we had in the first, and also there's no chance of memory leak, even if one of the strings throws an exception; stack unwinding will deallocate all memory.
    Last edited by Cat; 10-15-2006 at 04:41 PM.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  6. #51
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Declaring variables at the start of a function is another "C++--" bit of coding. Because we have something with which to initialize buffer, and because buffer2 isn't needed until later in the function, I might do somethig like this:
    Code:
    void SomeFunction(const std::string & str){
    
        std::string buffer("The contents of str are: ");
        buffer += str;
    
        std::string buffer2;
        if (str.length() >= 10)
            buffer2 = "Skipping the first 10 characters of str gives: " + str.substr(10);
        else
            buffer2 = "The string is less than 10 characters long";
    
        std::cout << buffer << std::endl << buffer2 << std::endl;
    
    }
    Another possibility would be to construct buffer with ("The contents of str are: " + str); which may or may not be more clear or efficient or both. Also, I'd consider using '\n' instead of endl, although I'm not sure if operator<< can throw in between the outputs making the explicit flush actually necessary.

  7. #52
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Quote Originally Posted by Daved
    Also, I'd consider using '\n' instead of endl, although I'm not sure if operator<< can throw in between the outputs making the explicit flush actually necessary.
    It can, if you have enabled exceptions for the iostream object. And if the underlying stream buffer throws. Thing is, if it throws an exception, do you really still care about the first output?
    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. #53
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    I agree. In this case you can't tell whether the original coder did that on purpose or not, and since either choice is valid I wouldn't consider that something that is "wrong" with the original code.

  9. #54
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Quote Originally Posted by CornedBee
    It can, if you have enabled exceptions for the iostream object. And if the underlying stream buffer throws. Thing is, if it throws an exception, do you really still care about the first output?
    Actually, that's a good point. That's an additional possible way that buffer[] and buffer2[] could be leaked in the original code. I edited my analysis to include that.
    Last edited by Cat; 10-15-2006 at 04:44 PM.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. noob with basic q's
    By SimplyComplex in forum C++ Programming
    Replies: 8
    Last Post: 11-19-2006, 01:17 PM
  2. [ANN] New script engine (Basic sintax)
    By MKTMK in forum C++ Programming
    Replies: 1
    Last Post: 11-01-2005, 10:28 AM
  3. what are your thoughts on visual basic?
    By orion- in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 09-22-2005, 04:28 AM
  4. visual basic vs C or C++
    By FOOTOO in forum Windows Programming
    Replies: 5
    Last Post: 02-06-2005, 08:41 PM
  5. Basic Window Creation, Dev C++ 4.9.9.0 Linking Error
    By Tronic in forum Windows Programming
    Replies: 2
    Last Post: 11-27-2004, 06:03 PM