函数调用中指向const的指针

问题描述 投票:3回答:2

我有一个整数数组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的原因)。

c pointers const
2个回答
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]

你想要什么是有道理的,但我无法想象一种一致的方式来宣布它。


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);
}

数组已经由地址给出

© www.soinside.com 2019 - 2024. All rights reserved.