传递常量矩阵

发布于 2024-08-03 16:25:58 字数 1747 浏览 3 评论 0原文

参考这个 问题,尤其是已接受的 litb 的回答,我想知道为什么 gcc 会抱怨这一点:

void func(const int (*ip)[3]) {
    printf("Value: %d\n", ip[1][1]);
}

int main() {
    int i[3][3] = { {0, 1, 2} , {3, 4, 5}, {6, 7, 8} };
    func(i);
    return 0;
}

如果我消除 const 编译器将保持静止。我是不是误会了什么?我想确保 func 不会修改我的数组。

编辑:如果我为矩阵定义数据类型,也会发生同样的事情:

typedef int Array[3][3];

void func(const Array *p) {
    printf("Value: %d\n", (*p)[1][1]);
}

int main() {
    Array a = { {0, 1, 2}, {3, 4, 5}, {6, 7, 8} };
    func(&a);
    return 0;
}

我接受,这种代码不是很 C 风格,更像是 C++。在 C++ 中,如果我将 Array 定义为包含所有矩阵行为的类,确实不会有问题。

class Array {...};

我想,我不太了解 C 中数组和数组数组的概念以及将它们传递给函数。有什么启示吗?

先感谢您。

EDIT2:同时,我对这个问题进行了一些思考,它似乎收敛到以下问题:C/C++ 隐式地将指向 int 的指针转换为指向 int 的指针代码>const int。因此,以下内容有效:

func(const int a[]) // aquivalent: func(const int *a)
{ ... }

int main() 
{
    int b[10];
    func(b);
    return 0;
}

但 C/C++ 不会将指向 n 个 int 数组的指针隐式转换为指向 n 个 const int 数组的指针。即使包含 n 个 int 的数组会隐式转换为包含 n 个 const int 的数组。不支持隐式转换中的这种间接级别。以下内容将被拒绝(至少在 C 中会出现警告):

func(const int a[][n]) // aquivalent: func(const int (*a)[n])
{ ... }

int main()
{
    int b[m][n];
    func(b);
    return  0;
}

这类似于 C++ 不会将类型 A 的模板隐式转换为类型 B 的模板,即使 A 可以隐式转换为 B 的问题。两个模板的类型完全不同。

这是正确的答案吗?

Referring to this question and especially the accepted answer of litb, I wonder why the gcc complain about this:

void func(const int (*ip)[3]) {
    printf("Value: %d\n", ip[1][1]);
}

int main() {
    int i[3][3] = { {0, 1, 2} , {3, 4, 5}, {6, 7, 8} };
    func(i);
    return 0;
}

If I eliminate the const the compiler keeps still. Did I something misunderstand? I wanted to be sure that func don't modify my array.

EDIT: The same thing happens if I define a data type for my matrix:

typedef int Array[3][3];

void func(const Array *p) {
    printf("Value: %d\n", (*p)[1][1]);
}

int main() {
    Array a = { {0, 1, 2}, {3, 4, 5}, {6, 7, 8} };
    func(&a);
    return 0;
}

I accept, this kind of code isn't very C style, more like C++. In C++ indeed there would be no problem if I define Array as a class containing all the matrix behavior.

class Array {...};

I suppose, I didn't understand very well the concept of arrays and arrays of arrays in C and passing them to functions. Any enlightenment?

Thank you in advance.

EDIT2: Meanwhile I chewed a bit on this problem and it seems to converge to the following question: C/C++ implicitly converts a pointer to an int to a pointer to an const int. Thus the following works:

func(const int a[]) // aquivalent: func(const int *a)
{ ... }

int main() 
{
    int b[10];
    func(b);
    return 0;
}

But C/C++ don't implicitly converts a pointer to an array of n ints to a pointer to an array of n const ints. Even though an array of n ints is implicitly converted to an array of n const ints. This level of indirection in the implicit conversion isn't supported. The following will be rejected (at least with a warning in C):

func(const int a[][n]) // aquivalent: func(const int (*a)[n])
{ ... }

int main()
{
    int b[m][n];
    func(b);
    return  0;
}

It's similar to the problem that C++ doesn't implicitly convert a template for the type A into a template of type B even if A can be implicitly converted to B. The two templates are of completely different types.

Is this the right answer?

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

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

发布评论

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

评论(2

紫罗兰の梦幻 2024-08-10 16:25:58

您的 i 变量是一个包含 3 个元素的数组。

当您将它传递给函数时,在函数内部,它变成指向第一个元素的指针。编译器可以将 const 添加到指针或指向的内容:3 个 int 的数组。然而,它不能将指向的内容从3 个整数的数组更改为3 个常量的数组

我认为你需要自己做演员。

#include <stdio.h>

typedef const int array_of_3_constants[3];

void func(int (* const i)[3]) {
  ++i[0][0];
  printf("Value: %d\n", i[1][1]);
}

void gunc(array_of_3_constants *i) {
  ++i[0][0];                              /* error */
  printf("Value: %d\n", i[1][1]);
}

int main(void) {
  int i[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
  func(i);
  func((array_of_3_constants*)i);         /* warning */
  gunc(i);                                /* warning */
  gunc((array_of_3_constants*)i);
  return 0;
}

Your i variable is an array with 3 elements.

When you pass it to a function, inside the function, it becomes a pointer to the first element. The compiler can add const either to the pointer or to the thing pointed to: an array of 3 ints. It cannot however change the thing pointed to from an array of 3 ints to an array of 3 constants.

I think you need to do the cast yourself.

#include <stdio.h>

typedef const int array_of_3_constants[3];

void func(int (* const i)[3]) {
  ++i[0][0];
  printf("Value: %d\n", i[1][1]);
}

void gunc(array_of_3_constants *i) {
  ++i[0][0];                              /* error */
  printf("Value: %d\n", i[1][1]);
}

int main(void) {
  int i[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
  func(i);
  func((array_of_3_constants*)i);         /* warning */
  gunc(i);                                /* warning */
  gunc((array_of_3_constants*)i);
  return 0;
}
花期渐远 2024-08-10 16:25:58

您不需要消除 const,只需通过将调用中的参数强制转换为 func 来传递兼容的值:

   func( (void *)i );

如果可能,最好将 i 声明为 const,但此 hack 应该有效。

You don't need to eliminate const, just pass a compatible value by casting the argument in the call to func:

   func( (void *)i );

If possible, it would be preferrable to declare i as const, but this hack should work.

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