为什么打印字符串数组输出十六进制?

时间:2015-05-13 22:06:23

标签: c++ string c++11

为什么以下程序打印" 0x2ffee4"到控制台?

#include <string>
#include <iostream>

using namespace std;

int main() {
    string city1[] = "toronto";
    cout << city1;
    return 0;
}

2 个答案:

答案 0 :(得分:18)

第一行不应该编译,但是GCC bug使得它编译并且行为等同于

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

(8,因为"toronto"是8个字符,包括终止空。是的,这意味着如果您使用"Chargoggagoggmanchauggagoggchaubunagungamaugg",它将创建一个包含46个字符串的数组,每个字符串存储"Chargoggagoggmanchauggagoggchaubunagungamaugg" 。)

毋庸置疑,您不应该依赖编译器错误。

根据海湾合作委员会的越野行为,city1将是std::string的数组;没有操作员<<超载支持打印这样的东西。相反,在std::cout << city1中,数组衰减到指向其第一个元素的指针,而是打印存储在指针中的地址。

你可能想写std::string city1 = "toronto";。一个字符串,而不是它的数组。

答案 1 :(得分:2)

T.C.给出的答案是的,我还想提一下,如果你打算打印出来的话,那就是多伦多&#34;使用cout到控制台然后你会想要这样做:

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;
}

如果您想在声明期间初始化任何类型的数组,则需要使用= {};设置用逗号分隔的每个数组元素。看看这段代码示例:

#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;
}

如果在声明数组时没有初始化数组,则必须指定数组的大小。

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;

}

如果您没有使用带有索引值的括号运算符发送到控制台输出流std :: cout,那么您获得的十六进制值是正确的 T.C已经说过;它返回第一个索引的地址。这就是为什么c / c ++数组和指针是相似的(它们不相同,但行为几乎彼此相似)。与数组的主要区别在于它们的大小是常量,大小必须在编译时知道,并且在创建具有更大大小的新数组时不必将内容存储到临时变量中而无法动态更改大小然后将所有数据复制到新数组中,然后清理旧数组。使用指针它们不会以这种方式运行,指针可以使用new在堆上动态分配,但是当该变量不再用于防止内存泄漏时,必须删除指针,如果指针在事先删除并且某些东西试图访问它内存地址不再有效并且不属于调用者,这些通常被视为未处理的异常,堆损坏等,并且会使程序崩溃。当你试图将它们超过它们的边界时,数组也是如此。

#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;
}