【问题标题】:How to pass an array of gmp_z to a function without a warning?如何在没有警告的情况下将 gmp_z 数组传递给函数?
【发布时间】:2013-11-10 13:42:10
【问题描述】:

背景

我正在使用 GMP 库的 C 接口,我需要操作整数数组。 GMP library is mpz_t 中整数的主要类型,GMP 使用了一个技巧来允许用户在没有显式分配的情况下使用 gmp_z,同时能够将它们作为指针传递。即gmp_z类型定义如下。

typedef struct
{
  int _mp_alloc;        
  int _mp_size;
  mp_limb_t *_mp_d;
} __mpz_struct;

typedef __mpz_struct mpz_t[1];

这很好,但是我在将 mpz_t 数组传递给在 const 数组上运行的函数时遇到了麻烦。

示例

为了举例说明这个简单的非 GMP 程序。

#include <stdio.h>

typedef struct {
  int x;
} x_struct;

typedef x_struct x_t[1];

void init_x(x_t x) {
  x->x = 23;
}

void print_x(const x_t x) {
  printf("x = %d\n", x->x);
}

// I'm just printing so taking a const array 
void print_x_array(const x_t* x_array, size_t n) {
  size_t i;
  for (i = 0; i < n; ++ i) {
    printf("x[%zu] = %d\n", i, x_array[i]->x);
  } 
}

int main() {
  x_t x; // I can declare x and it's allocated on the stack
  init_x(x);
  print_x(x); // Since x is an array, pointer is passed

  x_t x_array[3];
  init_x(x_array[0]);
  init_x(x_array[1]);
  init_x(x_array[2]);
  print_x_array(x_array, 3); // Compile warning
}

程序使用GMP技巧,只是炫耀用法。编译这个程序会给出一个恼人的警告

gcc test.c -o test
test.c: In function ‘main’:
test.c:33:3: warning: passing argument 1 of ‘print_x_array’ from incompatible pointer type [enabled by default]
test.c:17:6: note: expected ‘const struct x_struct (*)[1]’ but argument is of type ‘struct x_struct (*)[1]’

问题

由于我不是 C 专家,请有人能详细说明为什么会发生此警告。更重要的是,有没有办法在仍然使用 mpz_t(或示例中的 x_t)的同时绕过这个警告?

【问题讨论】:

  • print_x_array(&amp;x_array[0], 3)?
  • @chux 不起作用

标签: c arrays pointers warnings gmp


【解决方案1】:

直接投到const:

  print_x_array((const x_t *)x_array, 3); // Should be ok

【讨论】:

  • 虽然这可行,但它并不是一个完全令人满意的解决方案。我提供了许多这样的函数,函数的开发者/用户每次使用时都需要转换数组。
  • @DejanJovanović 然后将您的数组声明为const 或者将函数参数声明为非const
  • 此外 - 这是一个警告,您可以忽略它和/或禁用它。
  • 忽略大型项目的不兼容指针警告是不好的做法。
  • @DejanJovanović 我建议您使用另外两种修复方法。
【解决方案2】:

首先,请注意,您收到的编译器警告与 GMP 完全无关,它们将mpz_t 类型定义为大小为 1 的数组的策略,以便于库中的一些函数调用(但仅方便标量参数传递),也不利于将数组传递给函数,实际上它本身也不是一个真正的问题。

问题完全依赖于函数参数输入的const 声明,这不是真正的问题。有这样的定义很好,所以如果函数编写器试图修改传递给函数的对象,编译器会阻止。但是不能把负担放在函数调用者身上!

在我的设置(OpenSUSE、x86_64、gcc 版本 9.2.1)中,如果我不使用 -pedantic 编译器选项,您的代码不会发出警告并且工作正常。这是因为,正如 Michael Pankov 所说,(旧的)C 标准非常严格,有时很麻烦,而今天的编译器非常聪明。编译器现在可以执行您想要的操作,并且会为您提供正确的代码,请放心。此外,在您的环境中,调用该函数的人似乎比更改它的人多,因此可以确保输入不会被不当修改,并且您可以完全忽略该警告。

为了忽略这个针对 GCC 的特定警告检查 here,其他编译器也提供了这个选项。

关于函数参数输入检查here 上的const,我特别喜欢这个答案:“如果你的代码有很多人在处理它并且你的函数不平凡,那么你应该标记const尽你所能。在编写工业级代码时,你应该始终假设你的同事是精神病患者,他们试图以任何方式得到你(尤其是因为未来往往是你自己)。"。 p>

【讨论】:

    猜你喜欢
    • 2021-09-04
    • 2021-04-14
    • 1970-01-01
    • 2013-12-22
    • 1970-01-01
    • 1970-01-01
    • 2019-12-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多