c++ - 用于初始化结构的空指针转换

标签 c++ c

我正在学习面向对象的 C 编程(如何实现虚拟表),我看到了一些强制转换来进行初始化,我想知道是否:

1 - 是否有任何未定义的行为?

2 - 此代码可移植吗?

3 - 它在 C++ 中也有效(定义明确且可移植)吗?

在我正在研究的实际代码中,不是像这里这样的简单数据成员,而是指向构造函数、析构函数和克隆函数的函数指针,但我只对这些类型的转换是否定义良好感兴趣。

此代码使用 gcc 和 g++ 编译并按预期运行。

struct Point
{
        int x;
        int y;
};

struct Square
{
        struct Point *topLeft;
        struct Point *bottomRight;
        int area;
};

int main()
{
        void *square = calloc(1,sizeof(struct Square));
        * (struct Point **) square = (struct Point *) calloc(1,sizeof(struct Point));
        * ( ( (struct Point **) square) + 1) = (struct Point *) calloc(1,sizeof(struct Point));

        struct Square *sqrptr = (struct Square *) square;
        sqrptr->topLeft->x = 2;
        sqrptr->topLeft->y = 3;
        sqrptr->bottomRight->x = 5;
        sqrptr->bottomRight->y = 7;
        sqrptr->area = 20;

        printf("Values: %d %d %d %d\n", (** (struct Point **) square).x,
                                        (** (struct Point **) square).y,
                                        (** ( ( (struct Point **) square) + 1) ).x,
                                        (** ( ( (struct Point **) square) + 1) ).y );

        free(sqrptr->topLeft);
        free(sqrptr->bottomRight);
        free(sqrptr);
}

此外,根据 valgrind 的说法,不存在内存泄漏。

编辑:我刚刚尝试使用 C++ 风格的转换,g++ 没有给出任何错误或警告消息。

最佳答案

由于访问结构中的第二个数据成员,我发布的代码段具有未定义的行为:

* ( ( (struct Point **) square) + 1) = (struct Point *) calloc(1,sizeof(struct Point));

编译器可以对齐 Square 结构,以便第二个数据成员不会立即在第一个结构 Point 之后开始。

但是,访问第一个数据成员在 C 和 C++ 中都是有效且定义良好的,因为第一个数据成员之前没有填充:

struct alignment C/C++

(C11, 6.7.2.1p15) "There may be unnamed padding within a structure object, but not at its beginning."

(C++11, 9.2p20) "There might therefore be unnamed padding within a standard-layout struct object, but not at its beginning, as necessary to achieve appropriate alignment"

因此,在结构的开头,我可以放置一个指向 VirtualTable 结构的指针,其中包含指向初始值设定项和清理函数的函数指针,并在纯 C 中实现面向对象的行为。这在 C++ 中也有效。

关于c++ - 用于初始化结构的空指针转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57236295/

相关文章:

c - 将数组分配给 C 中的函数指针参数

c - 如何快速搜索库中 undefined reference 。

c - Eclipse kepler (Windows 8.1) 中 Unresolved inclusion : <stdio. h>

c++ - 一次设置多个数组索引?复合文字?

C++ 如何阻止随机引擎产生负数?

c++ - 字符串s中是整数n吗? 4 在 Ab56c4D 中吗? (C++)

c++ - g++ 解析错误 ":"

c - 如何使用c或javascript或lua查找XML文件的父节点?

c - 从C中的结尾访问数组?

c++ - 返回类型协方差与智能指针