【问题标题】:Rewrite C++ class in C [duplicate]用C重写C++类[重复]
【发布时间】:2020-10-18 21:43:46
【问题描述】:

所以,我在重写我用 C 编写的 C++ 类时遇到了一些麻烦。

C++ 类有一些私有属性:

int grid_width;
int grid_height;
const int group_width = 2;
const int group_height = 4;
std::vector<int> buffer;

它是这样初始化的:

grid::grid(int width, int height) {
            this->grid_width = width;
            this->grid_height = height;
            buffer.resize(this->grid_width / this->group_width * this->grid_height / this->group_height, 0);
    
}

它还带有一个清晰的功能,如下所示:

void grid::clear() {
    // get_buffer_size returns elements in the buffer vector
    for (int i = 0; i < get_buffer_size(); ++i) {
        buffer[i] = 0x00;
    }
}

现在,我尝试用 C 重写它看起来有点像这样:

typedef struct
{
    int width;
    int height;
    int *buffer;
} grid;

grid *grid_new(int grid_width, int grid_height)
{
    if ((grid_width % 2 != 0) || (grid_height % 4 != 0))
        return NULL;

    int group_height = 4;
    int group_width = 2;

    grid *p_grid = calloc(grid_width / group_width * grid_height / group_height, sizeof(int));
    p_grid->width = grid_width;
    p_grid->height = grid_height;

    return p_grid;
}

void grid_free(grid *p_grid)
{
    free(p_grid->buffer);
    free(p_grid);
}

void grid_clear(grid *g)
{
    // ToDo: Iterate over all elements in the buffer
    int elements = sizeof(g->buffer) / sizeof(int);
    printf("Elements: %i", elements);
}

但由于某种原因,我的 C 代码中的元素数量总是 2? 有谁知道我在哪里搞砸了?

如果网格用 4 和 8 初始化,预期的缓冲区大小应该是 4,而不是 2。如果用 10 和 24 初始化,预期的大小将是 30,但在我的 C 示例中它仍然是 2 .

【问题讨论】:

  • sizeof(g-&gt;buffer) -- 这并不像你认为的那样。这不会给您分配的字节数。无论您使用的是C++ 还是C,都是这种情况。
  • 如果您需要知道指向数组有多少元素,您需要将该值存储在某处。 std::vector 在内部执行此操作,在 C 中您必须自己执行此操作(除非您使用具有很好的动态数组实现的库)
  • 一旦你解决了@PaulMcKenzie 提到的问题,你就会遇到其他问题。请注意,您只有一个calloc,但有两个frees。你也永远不会初始化p_grid-&gt;buffer。我假设您打算让 callocbuffer 分配空间,但这不是您使用它的方式。
  • 另外,信不信由你,C 允许您按值返回struct,就像 C++ 一样。无需为grid_new 函数返回grid *。声明一个本地grid,正确初始化,然后返回..grid grid_new(int grid_width, int grid_height)。以这种方式做事也可能会阻止@MilesBudnek 指出的错误

标签: c++ c arrays memory-management struct


【解决方案1】:

您的grid_new 正在分配一个由grid 结构组成的数组,而不是一个具有正确数量元素的grid

你需要设置buffer

此外,网格中元素的数量基于宽度/高度和 not sizeof(g-&gt;buffer) 这是 pointernot它指向的区域

这是重构后的代码:

const int group_height = 4;
const int group_width = 2;

typedef struct {
    int width;
    int height;
    int *buffer;
} grid;

grid *
grid_new(int grid_width, int grid_height)
{
    if ((grid_width % 2 != 0) || (grid_height % 4 != 0))
        return NULL;

    grid *p_grid = calloc(1,sizeof(*p_grid));

    // FIXME -- why???
    grid_width /= group_width;
    grid_height /= group_height;

    p_grid->width = grid_width;
    p_grid->height = grid_height;

    p_grid->buffer = calloc(grid_width * grid_height,sizeof(int));

    return p_grid;
}

void
grid_free(grid *p_grid)
{
    free(p_grid->buffer);
    free(p_grid);
}

void
grid_clear(grid *g)
{
    // ToDo: Iterate over all elements in the buffer
    int elements = g->width * g->height;

    printf("Elements: %i", elements);
}

【讨论】:

  • 我明白了。这就说得通了。必须习惯这一点——从 C++ 切换到 C 会带来一些惊喜;)这也是推荐的 C 风格指南,将返回类型放在函数签名上方的单独行中吗?
  • 大多数风格指南推荐它。但是 linux kernel 风格指南说它应该在同一行。我这样做有几个原因:(1) 更清晰/更清晰 [IMO,基于 40 年的经验] (2) 您可以使用 regex 轻松找到函数定义(例如):@ 987654328@ (3) 它有助于保持行是]
【解决方案2】:

'sizeof' 返回指定类型占用的字节数。在这种情况下 sizeof(g->buffer) 等于 sizeof(int*) 并且因为您使用的是 x64 处理器,所以所有指针的 sizeof 都是 8。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    • 2011-11-07
    • 2011-08-15
    相关资源
    最近更新 更多