函数调用中指向const的指针

时间:2019-02-22 07:58:56

标签: c pointers const

我有一个整数数组int foo[3],我想将其传递给另一个函数。我想完成两件事:

  • 通过引用传递它
  • 将其设置为常量,因为不应对其进行修改。

我定义的功能是:

void print_foo(const int(*const foo)[3]) {

    // Print the second integer
    printf("%d\n", (*foo)[1]);
}

我称之为:

int foo[3] = {1, 2, 3};

print_foo(&foo);

当我用MinGW的gcc进行编译时,会收到警告:

warning: passing arg 1 of `print_foo` from incompatible pointer type

我想了解我在做错什么。

注意: 我可以隐藏没有第一个const的声明函数的警告,如下所示:

void print_foo(int(*const foo)[3])

但是这似乎是一种解决方法,因为我不仅希望指针地址是恒定的,而且还希望内存的内容是恒定的(这就是两个const的原因)。

2 个答案:

答案 0 :(得分:3)

只要这样做:

#include <stdio.h>

// note can also use "const int foo[3]" but in that
// case 3 is nothing more than a comment for a reader
void print_foo(const int foo[])
{
  // Print the second integer
  printf("%d\n", foo[1]);
}

int main()
{
  int foo[3] = {1, 2, 3};

  print_foo(foo);
}

该数组已经由地址给出

答案 1 :(得分:2)

有趣的是,我可以在没有警告的情况下使用CLang版本3.4.1和6.0.0编译以下代码:

#include <stdio.h>

void print_foo(const int (* const foo)[3]) {
    printf("%d - size: %lu\n", (*foo)[1], sizeof(*foo));
}
int main() {
    int foo[3] = {1,2,3};
    print_foo(&foo);
    return 0;
}

在我的32位系统上,输出为2 - 12,这证明sizeof(*foo)具有期望值。

但是我会说gcc在这里是正确的,而Clang允许它作为扩展。

标准(适用于C11的n1570草案)在6.2.7兼容类型和复合类型§1中说:

  

如果两个类型相同,则它们具有兼容类型。的其他规则   在6.7.2中对类型说明符,6.7.3对类型限定符,6.7.6对于声明符和6.7.3类型限定符§10

中描述了确定两种类型是否兼容的描述      

要使两个合格的类型兼容,两个都应具有兼容类型的相同合格版本

因此类型必须具有相同的常数才能兼容。

但是在函数调用中传递参数具有与赋值相同的语义,并且6.5.16.1在其约束中说明了简单赋值:

  

应满足以下条件之一:
...
  左操作数具有原子,合格或不合格的指针类型,并且(考虑到左操作数在左值转换后将具有的类型)两个操作数都是指向兼容类型的合格或不合格版本的指针,并且左侧指向的类型具有全部右侧指向的类型的限定词

好的,即使不兼容,也可以将int (*)[3]分配给int (const *)[3]

但是int [3]const int[3]是不同的类型,因此无法将int (*)[3]分配给const int (*)[3]const int (const *)[3]

您想要的东西是有道理的,但是我无法想象用一种一致的方式声明它。