7

Why does the following program print "0x2ffee4" to the console?

#include <string>
#include <iostream>

using namespace std;

int main() {
    string city1[] = "toronto";
    cout << city1;
    return 0;
}
7
  • 3
    Shouldn't even compile Commented May 13, 2015 at 22:07
  • 1
    OMG not that GCC bug again... Commented May 13, 2015 at 22:07
  • @chris stackoverflow.com/questions/21481462/…; gcc.gnu.org/bugzilla/show_bug.cgi?id=60009 Commented May 13, 2015 at 22:08
  • hi. could you please clarify what that is. Commented May 13, 2015 at 22:09
  • @T.C., Your comment brought back memories of annoyingly common questions. Too bad I haven't encountered this one. Commented May 13, 2015 at 22:10

2 Answers 2

18

The first line shouldn't compile, but there's a GCC bug that makes it compile and behave equivalently to something like

std::string city1[] = {"toronto", "toronto", "toronto", "toronto",
                       "toronto", "toronto", "toronto", "toronto"};

(8, because "toronto" is 8 characters including the terminating null. Yes, that means that if you used "Chargoggagoggmanchauggagoggchaubunagungamaugg", it would create an array of 46 strings, each storing "Chargoggagoggmanchauggagoggchaubunagungamaugg".)

Needless to say, you shouldn't rely on a compiler bug.

Under GCC's buggy behavior, city1 would be an array of std::strings; there's no operator << overload that support printing such a thing. Instead, in std::cout << city1, the array decays to a pointer to its first element, and the address stored in the pointer is printed instead.

You probably meant to write std::string city1 = "toronto";. One string, not an array of it.

Sign up to request clarification or add additional context in comments.

2 Comments

He gets it, kudos @wazeeer, but for the TL;DR crowd, T.C., you should move the note about why it printed the address instead of the string closer to the top of the answer since that section is the answer.
@user4581301 I dunno, to me the answer is "it shouldn't be printing anything because it won't compile"...
2

The answer given by T.C. is correct, I would also like to mention that if you was expecting to print out "toronto" to the console using cout then you would want to do this:

include <string>
include <iostream>

int main() {
    using namespace std;

    // string city1[] = "toronto"; // Compiler Error - Do Next Line Instead
    string city1[] = { "toronto" };
    cout << city1[0];

    return 0;
}

Any time you want to initialize an array of any type during declaration you need to use = { }; To set each array's element separated by commas. Look at this code sample:

#include <string>
#include <iostream>

int main() {
    using namespace std;

    string cities[] = { "New York", "Philadelphia", "Chicago", "Boston" };

    // Same As Above Except Size Of Array Is Defined First Then The Elements
    string cities[4];
    cities[0] = "New York";
    cities[1] = "Philadelphia";
    cities[2] = "Chicago";
    cities[3] = "Boston";

    unsigned index = 0;
    for ( ; index < 4; index++ ) {
        cout << cities[index] << endl;
    }

    return 0;
}

If you are not initializing the array when declaring it then you must specify the array's size.

int main() {
    int iArray[]; // Compiler Error
    int iArray[] = { 4, 3, 2, 1, 6 }; // Okay and is the same as

    int iArray[5];  // Okay
    iArray[0] = 4;
    iArray[1] = 3;
    iArray[2] = 2;
    iArray[3] = 1;
    iArray[4] = 6;

    return 0;

}

If you are not using the bracket operator with an index value to send to the console output stream std::cout then the hex value you are getting is correct as T.C had already stated; it is returning the address of the first index. This is why in c / c++ arrays and pointers are similar (they are not the same, but behave almost like one another). The main difference with arrays is that they are constant in size, the size has to be known at compile time, and can not be dynamically changed in size without having to store the contents into a temp variable while creating a new array with a larger size then copying all the data into the new array and then cleaning up the old array. With pointers they do not behave this way, pointers can be dynamically allocated on the heap using new, but also must be deleted when that variable has no more use to prevent memory leaks, if the pointer is delete before hand and something tries to access it that memory address is no longer valid and doesn't belong to the caller, these are normally seen as unhandled exceptions, heap corruption, etc. and will crash your program. The same goes for arrays when you try to index them past their bounds.

#include <iostream>

int main() {
    // Arrays Are 0 Indexed
    int iArray[3] = { 1, 2, 3 };

    // If you try to do this to access the last element
    std::cout << iArray[3] << std::endl; // Program Will Crash

    // Since Arrays Are 0 Indexed And The Size Of The Array Is 3
    // The 3rd Value Is Indexed At 2, And By Trying To Index Location Of Array
    // At 3, This Memory Doesn't Belong To You, And It Is Undefined Behavior.
    // This Memory Could Contain Nothing, Random Data, Or Even Data That Belongs To 
    // Something Else Which If Changed Can Even Cause System Failure          

    return 0;
} 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.