改变类大小的向量

发布于 2024-12-07 21:52:02 字数 3278 浏览 0 评论 0原文

编辑:
尽管格式错误,但这个问题有一个很好的收获。因此,我正在编辑此问题,以便以更好的格式保留此问题,以供将来偶然发现此问题的访问者使用。


在下面的代码示例中,有人可以解释为什么在 memcpy 之后类的大小与预期不同吗?原因是什么?

这里是 Ideone 上的在线演示。

#include<iostream>
#include<vector>
#include<cstdio>
#include<cstring>

using namespace std;

class A
{
    public:
        int a;
        virtual void f1() { cout <<"inside a::f1\n"; }
        A() { a = 1; }
};

class B
{
    public:
        int b;
        virtual void f2() { cout <<"inside b::f2\n"; }
        virtual void f5() { cout <<"inside b::f5\n"; }
        B() { b = 2; }
};

class C : public A, public B
{
    public:
        int c;
        void f1() { cout <<"inside c::f1\n"; }
        void f2() { cout <<"inside c::f2\n"; }

        virtual void f3() { cout <<"inside c::f3\n"; }
        virtual void f4() { cout <<"inside c::f4\n"; }
        C() { c = 3; }
};


int fun()
{
    int a = 1;
    return a * 2;
}

int main()
{
    C c;
    C c2;
    int (*g)() = &fun;

    void (A::*g1)() = &A::f1;
    void (C::*g2)();

    g2 = &C::f1;
    (c.*g2)();

    printf("%p\n",g2);
    cout << sizeof(g2) << endl;

    g2 = &C::f2;
    (c.*g2)();

    printf("%p\n", g2);

    // Why is the output 1 here in g++ or visual C++?
    cout << g2;
    // Why is the sizeof returning 8? Please explain.
    cout << sizeof(g2) << endl;

    g2 = &C::f1;
    std::vector<unsigned char> a_vec(sizeof(g2));

    memcpy(&a_vec[0], &g2, sizeof(g2));
    for(size_t i = 0; i < sizeof(g2); ++i)     
    {         
        cout << hex << static_cast<unsigned>(a_vec[i]) << " ";
    } 
    cout << endl;

    g2 = &C::f2;
    std::vector<unsigned char> a_vec1(sizeof(g2));
    memcpy(&a_vec1[0], &g2, sizeof(g2));

    for(size_t i = 0; i < sizeof(g2); ++i)     
    {         
        cout << hex << static_cast<unsigned>(a_vec1[i]) << " ";
    } 
    cout << endl;

    cout << sizeof(g) <<endl;
    cout << sizeof(g1) <<endl;
    cout << sizeof(g2) <<endl;

    // Why is sizeof(C) printing 14 and not 20 in visual C++?
    // If yes why is this so ?
    cout << sizeof(C) << endl;
    cout << sizeof(c2) << endl;
    cout << (&c) << endl;
    cout << c.a << endl;
    cout << c.b << endl;
    cout << c.c << endl;

    return 0;
}

从上面的代码示例中,我得到的输出是:

inside c::f1
0x1
8
inside c::f2
0x5
18
1 0 0 0 0 0 0 0 
5 0 0 0 0 0 0 0 
4
8
8
14
14
0xbffe375c
1
2
3   

以下是我的问题:

  1. 为什么这里的输出 1 是在 g++ 或 Visual C++ 中?

    <块引用>

    cout << g2;

  2. 为什么sizeof返回8?请解释一下。

    <块引用>

    cout <<大小(g2) <<结束;

  3. 为什么在 Visual C++ 中 sizeof(C) 打印 14 而不是 20?如果是,为什么会这样?

    <块引用>

    cout <<大小(C) <<结束;

EDIT:
Though badly formatted this Question had a nice catch.So, I am editing this to retain this in a better format for future visitors who stumble across this question.


In the code sample below can someone please explain Why is the size of class different than expected after memcpy? What is the reason?

Here is the online demo on Ideone.

#include<iostream>
#include<vector>
#include<cstdio>
#include<cstring>

using namespace std;

class A
{
    public:
        int a;
        virtual void f1() { cout <<"inside a::f1\n"; }
        A() { a = 1; }
};

class B
{
    public:
        int b;
        virtual void f2() { cout <<"inside b::f2\n"; }
        virtual void f5() { cout <<"inside b::f5\n"; }
        B() { b = 2; }
};

class C : public A, public B
{
    public:
        int c;
        void f1() { cout <<"inside c::f1\n"; }
        void f2() { cout <<"inside c::f2\n"; }

        virtual void f3() { cout <<"inside c::f3\n"; }
        virtual void f4() { cout <<"inside c::f4\n"; }
        C() { c = 3; }
};


int fun()
{
    int a = 1;
    return a * 2;
}

int main()
{
    C c;
    C c2;
    int (*g)() = &fun;

    void (A::*g1)() = &A::f1;
    void (C::*g2)();

    g2 = &C::f1;
    (c.*g2)();

    printf("%p\n",g2);
    cout << sizeof(g2) << endl;

    g2 = &C::f2;
    (c.*g2)();

    printf("%p\n", g2);

    // Why is the output 1 here in g++ or visual C++?
    cout << g2;
    // Why is the sizeof returning 8? Please explain.
    cout << sizeof(g2) << endl;

    g2 = &C::f1;
    std::vector<unsigned char> a_vec(sizeof(g2));

    memcpy(&a_vec[0], &g2, sizeof(g2));
    for(size_t i = 0; i < sizeof(g2); ++i)     
    {         
        cout << hex << static_cast<unsigned>(a_vec[i]) << " ";
    } 
    cout << endl;

    g2 = &C::f2;
    std::vector<unsigned char> a_vec1(sizeof(g2));
    memcpy(&a_vec1[0], &g2, sizeof(g2));

    for(size_t i = 0; i < sizeof(g2); ++i)     
    {         
        cout << hex << static_cast<unsigned>(a_vec1[i]) << " ";
    } 
    cout << endl;

    cout << sizeof(g) <<endl;
    cout << sizeof(g1) <<endl;
    cout << sizeof(g2) <<endl;

    // Why is sizeof(C) printing 14 and not 20 in visual C++?
    // If yes why is this so ?
    cout << sizeof(C) << endl;
    cout << sizeof(c2) << endl;
    cout << (&c) << endl;
    cout << c.a << endl;
    cout << c.b << endl;
    cout << c.c << endl;

    return 0;
}

From the above code sample the Output I get is:

inside c::f1
0x1
8
inside c::f2
0x5
18
1 0 0 0 0 0 0 0 
5 0 0 0 0 0 0 0 
4
8
8
14
14
0xbffe375c
1
2
3   

Following are my Questions:

  1. Why is the output 1 here in g++ or visual C++?

    cout << g2;

  2. Why is the sizeof returning 8? Please explain.

    cout << sizeof(g2) << endl;

  3. Why is sizeof(C) printing 14 and not 20 in visual C++? If yes why is this so?

    cout << sizeof(C) << endl;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

拧巴小姐 2024-12-14 21:52:02

为什么sizeof返回8。请解释一下?

cout <<sizeof(g2)<<endl;  

返回 8,因为 g2 是一个指针,而您的环境中指针的大小是 8。


为什么在 g++ 中输出 1还是 Visual C++?

cout << g2; 

<<运算符 没有接受指针的重载版本。因此,指针被转换为 bool 类型,值为 1,并且 cout 打印它。

C++ 标准允许这样做:

C++03 标准 4.12 布尔转换

1 算术、枚举、指针或指向成员类型的指针的右值可以转换为 bool 类型的右值。


为什么在 Visual C++ 中 sizeof(C) 打印 14 而不是 20

cout<<sizeof(C)<<endl;  

它显示 的大小>C 正确地只是十六进制(十六进制的 14 == 十进制的 20)。这是因为您之前使用了hex I/O 操纵器来打印地址。

cout<<dec<<sizeof(C)<<endl;

将再次将 I/O 操纵器设置为十进制模式,并且将按照您的预期输出 20


关于 printf 和类型安全的一句话:

printf 不是类型安全的。使用 printf 时,这是用户的责任将正确的格式描述符和数据类型传递给它。如果不匹配,则会出现未定义行为。未定义的行为意味着程序可能会崩溃或显示任何奇怪的行为。

printf("%p\n", g2);

是未定义行为的一个示例,格式描述符和数据类型不匹配。请注意,编译器确实会抱怨这一点,您应该始终留意并检查编译器发出的此类警告。

警告:格式“%p”需要类型“void*”,但参数 2 的类型为“void (C::*)()”

Why is the sizeof returning 8. Please explain?

cout <<sizeof(g2)<<endl;  

returns 8 because g2 is a pointer and size of an pointer on your enviornment is 8.


Why is the output 1 here in g++ or visual C++?

cout << g2; 

The << operator does not have an overloaded version which accepts a pointer. So the pointer gets converted to a bool type, with a value 1, and cout prints it.

The C++ Standard allows this:

C++03 Standard 4.12 Boolean conversions

1 An rvalue of arithmetic, enumeration, pointer, or pointer to member type can be converted to an rvalue of type bool.


Why is sizeof(C) printing 14 and not 20 in visual C++.

cout<<sizeof(C)<<endl;  

It displays the size of C correctly just in hexadecimal(14 in hex == 20 in decimal). This is because you used the hex I/O manippulator to print an address before.

cout<<dec<<sizeof(C)<<endl;

will set the I/O manipulator to decimal mode again and it will output 20 as you expect.


A word about printf and type safety:

printf is not type safe.When using printf it is the users responsibility to pass the proper formart descriptor and data type to it. If there is a mismatch then an Undefined Behavior will occur. An Undefined behavior means that the program might crash or show any weird behavior.

printf( "%p\n", g2 );

Is an example of Undefined Behavior, there is a mismatch in the format descriptor and the data type. Note that the compiler does complain about this and you should always look out and check such warnings emitted by the compiler.

warning: format ‘%p’ expects type ‘void*’, but argument 2 has type ‘void (C::*)()’

灰色世界里的红玫瑰 2024-12-14 21:52:02

给定类型的 sizeof 结果永远不会改变。 (至少对于一个
符合 C++ 程序。我相信 g++ 支持 C++ 中的 VLA,作为
扩展名,并且包含 VLA 的对象的 size 可能会发生变化。)
关于您的明确问题:

printf( "%p\n", g2 );

是未定义的行为。您将指向成员的指针传递给输出
需要 void* 的格式化程序。 (g++ 会对此发出警告,我
相信,至少有某些选择。)你可能会得到
任何事情(包括程序崩溃)。指向成员的指针不是
void*,且无法转换为void*

cout << g2;

我不敢相信这能编译。

cout << sizeof(g2) << endl;

sizeof(g2) 返回 8,因为这是指向成员的指针的大小
在您的系统上。

cout << sizeof(C) << endl;

打印 14,因为这是该类型对象的十六进制大小
您系统上的C。换句话说,sizeof(C) 是 20。因为您已经
将输出设置为hex,并且永远不要重置它,输出是十六进制的。

The results of sizeof for a given type never change. (At least for a
conforming C++ program. g++, I believe, supports VLAs in C++, as an
extension, and the sizeof an object containing a VLA might change.)
With regards to your explicit questions:

printf( "%p\n", g2 );

is undefined behavior. You're passing a pointer to member to an output
formatter which requires a void*. (g++ will warn about this, I
believe, at least with certain options.) You might get just about
anything (including a program crash). Pointers to members are not
void*, and can't be converted to void*.

cout << g2;

I can't believe that this compiles.

cout << sizeof(g2) << endl;

sizeof(g2) returns 8 because this is the size of a pointer to member
on your system.

cout << sizeof(C) << endl;

Prints 14 because this is the size in hexadecimal of an object of type
C on your system. In other words, sizeof(C) is 20. Since you've
set output for hex, and never reset it, the output is hexadecimal.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文