【问题标题】:Understanding Character array initialization and data storing了解字符数组初始化和数据存储
【发布时间】:2017-09-12 17:52:07
【问题描述】:

我试图了解字符数组是如何初始化的以及数据是如何存储的。

我做了一个测试,结果是这样的

struct test
{
    char one  [2];
    char two  [2];
    char three[2];
};

test * testptr;

char testchar[] = "hello";

testptr = reinterpret_cast<test*>(testchar);

cout << testptr->one << endl;
cout << testptr->two << endl;
cout << testptr->three << endl;

我期待看到类似的东西:

he
ll
o

但是,当我编译时,我得到:

hello
llo
o

我不明白 onetwo 包含比大小本身更多的字符,当我为变量执行 sizeof 时,它们都变成了 2,就像它的大小一样已初始化。

如果完成了这样的cout

for (int i = 0; i < 6; i++)
{
    cout << testptr->one[i] << endl;
}

结果是:

h
e
l
l
o

如果我超过6,它要么是空的,要么是垃圾。

我知道我可以使用memcpy 很好地将数量字节分配到数组中,但我试图了解固定大小的字符数组如何能够存储比它所能容纳的更多的内容。

【问题讨论】:

    标签: c++ arrays char reinterpret-cast


    【解决方案1】:

    reinterpret_castchar[]struct* 时,指向onetwothree 的指针分别指向输入字符串中的第 0、第 2 和第 4 个字符(有一个空格两个,因为每个变量的大小都是两个,所以像ptrptr + 2ptr + 2 + 2)。

    h e l l o
    ^   ^   ^
    |   |   |
    0   2   4
    

    此外,C++ 中的 char* 以 NULL 字符 ('\0') 终止。因此,当您打印onetwothree 的值时,我们会看到从头到尾的所有字符。

    【讨论】:

    • 我明白了,但是,我仍然不明白 onetwo 的大小如何,仍然能够容纳超过它的大小。无论如何要限制,只允许one 存储he,并允许two 存储ll
    • 他们没有持有超过他们的大小。由于数组存储在连续内存中,因此越界访问(超过 2 个字符)将为您提供字符串中的下一个条目。如果不是这种情况,您将获得一些垃圾价值。因为您正在尝试做的是未定义的行为
    • 我明白了,有没有我可以使用reinterpret_cast,当我coutonetwothree 时,我将能够得到我想要的数据上面,one = hetwo = llthree = o,从技术上讲,three 已经指向数组中的最后一个字符。
    • 我认为唯一的选择是打印每个字符直到达到大小。不过不确定。
    【解决方案2】:

    您可以在 for 循环中打印每个 char 数组值,而不是使用 cout,直到它们的大小达到您的要求。

    #include <string.h> 
    #include <iostream>
    using namespace std;
    struct test
    {
        char one  [2];
        char two  [2];
        char three[2];
        test()
        {
            cout<<"in test"<<endl;
            memset(&one,NULL,3);
            memset(&two,NULL,3);
            memset(&three,NULL,3);
        }
        void display()
        {
            cout<<" one   two   three"<<endl;
            for(int i=0;i<2;i++)
            {
                cout<<one[i]<<"  "<<two[i]<<"  "<<three[i]<<endl;
            }
            cout<<endl;
       }
    
    };
    main()
    {
        test  testobj;
        test  *testptr = &testobj;
        char testchar[] = "hello";
        testptr->display();
        testptr = reinterpret_cast<test*>(testchar);
        testptr->display();
        cout << testptr->one << endl;
        cout << testptr->two << endl;
        cout << testptr->three << endl;
    }
    

    输出:

    在测试中 一二三

    一二三

    h l o

    e l

    你好 洛 o

    【讨论】:

    • 但我需要的是在reinterpret_cast 之后,我需要变量只包含它们所拥有的,而不是必须在\0 所在的字符串末尾,否则我将拥有恢复使用memcpy 来完成它。
    • 它将仅包含复制的 2 个字节,这只是因为您直接打印它而没有逐字节打印,直到 NULL 终止。所以这就是我让 for 循环显示每个 char 数组中的内容的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-29
    相关资源
    最近更新 更多