【发布时间】:2021-07-03 15:36:03
【问题描述】:
在以下示例中,非 const 限定指针 b 被传递给 func,它需要一个指向 const 限定类型的指针。因此,我希望编译器发出警告。但是,如果我用 clang 和 -Wall -Wextra -pedantic 编译这个程序,则没有警告。这是为什么呢?
#include <stdlib.h>
#include <string.h>
#define N 5
struct Bear {
int n;
int v;
int *data;
};
void func (const struct Bear *bear, int *data, const size_t n)
{
memcpy (bear->data, data, n);
}
int main (void)
{
int arr[N];
int *mem = malloc (N*sizeof (int));
if (mem == NULL) return -1;
struct Bear *b = &(struct Bear){1, 2, mem};
func (b, arr, N);
free (mem);
return 0;
}
此外,如果我将结构初始化的行更改为
const struct Bear *b = &(const struct Bear){1, 2, mem};
仍然没有警告。我知道结构声明中的const 应用于其字段,因此func 中的bear->v = 11; 显然是一个错误(并产生警告)。但是,对于指针来说,这似乎并不成立。
这是未定义的行为吗?我在这里错过了什么?
【问题讨论】:
-
您可以将非常量传递给 const。当您尝试将 const 传递给非 const 时会出现警告,因为这表明可以修改指针目标。例如,
strcpy之类的东西采用const char *源参数,表明它没有被修改,但您可以传递任何char *作为该参数。 -
在函数声明中将指针声明为指向 const 的指针只是告诉编译器(和使用该函数的程序员)该函数不会更改指针引用的对象。它不需要您传递指向 const 的指针。换句话说,从程序员的角度来看,在函数声明中使用 const 只不过是关于函数行为的文档。从编译器的角度来看,这是一个优化提示。
-
请注意,
memcpy (bear->data, data, n);不会更改指针bear->data,而只会更改它指向的内容。memcpy的原型保证了它,因为第一个操作符是带有const限定符的指针。