使用地址运算符在 c 函数中传递数组会发出警告
Passing array in a c function using address operator gives a warning
我试图将一个数组传递给一个方法。我尝试了以下方法:
- func2(ARRAY_NAME, length) => 有效,无警告
- func2(&ARRAY_NAME[0], length) => 有效,无警告
- func2(&ARRAY_NAME, length) => 有效,但有警告
我不明白为什么最后一个(#3)给出警告。 &ARRAY_NAME 在 memset、memcpy 等中工作时没有警告。为什么在自定义方法中出现问题?
警告信息:
functionTest.c:35:11: warning: passing argument 1 of ‘func2’ from incompatible pointer type [-Wincompatible-pointer-types]
35 | func2(&temp, ARRAY_SIZE);
| ^~~~~
| |
| unsigned char (*)[200]
functionTest.c:8:27: note: expected ‘unsigned char *’ but argument is of type ‘unsigned char (*)[200]’
8 | void func2(unsigned char* buf, int length)
代码
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#define ARRAY_SIZE 200
void func2(unsigned char* buf, int length)
{
// Change data of any index
buf[0] = 100;
buf[10] = 200;
}
void func1()
{
unsigned char temp[ARRAY_SIZE];
// Initialize
memset(temp, 0, sizeof(temp));
for(int i = 0; i < ARRAY_SIZE; i++)
{
printf("\t%d", temp[i]);
}
printf("\n-----------------------------------------------\n");
printf("Address : %p\n", &temp);
printf("Address of 0th index : %p\n", &temp[0]);
printf("\n-----------------------------------------------\n");
// Pass array in func2
func2(&temp, ARRAY_SIZE); // WARNING
func2(&temp[0], ARRAY_SIZE); // NO WARNING
for(int i = 0; i < ARRAY_SIZE; i++)
{
printf("\t%d", temp[i]);
}
printf("\n-----------------------------------------------\n");
}
int main()
{
func1();
return 0;
}
错误信息中写得很清楚
functionTest.c:8:27: note: expected ‘unsigned char *’ but argument is of type ‘unsigned char (*)[200]’
8 | void func2(unsigned char* buf, int length)
该函数需要一个类型为 unsigned char *
的指针,但参数表达式 &temp
的类型为 unsigned char ( * )[200]
并且没有从一种指针类型到另一种指针类型的隐式转换,尽管值为指针相同:数组占用内存范围的地址。
至于函数memset
和memcpy
则它们处理void *
类型的指针。例如,函数 memset
具有以下声明
void *memset(void *s, int c, size_t n);
指向其他类型对象的指针可以隐式转换为void *
类型的指针。
来自 C 标准(6.3.2.3 指针)
1 A pointer to void may be converted to or from a pointer to any
object type. A pointer to any object type may be converted to a
pointer to void and back again; the result shall compare equal to the
original pointer.
func2
被声明为具有 unsigned char *
类型的第一个参数,因此应将其传递给与 unsigned char
兼容的类型的指针或指向 [=13= 的指针], 将自动转换为 unsigned char *
.
使用 func2(temp, ARRAY_SIZE)
,数组 temp
自动转换为指向其第一个元素的指针。这个指针是一个unsigned char *
,满足要求
对于func2(&temp[0], ARRAY_SIZE)
,temp[0]
是一个unsigned char
,所以&temp[0]
是一个指向unsigned char
的指针。这样就满足要求了。
和func2(&temp, ARRAY_SIZE)
一样,&temp
是指向unsigned char
的200个元素的数组的指针。它指向与&temp[0]
相同的位置,只是它的类型不同。它是一个指向数组的指针,而不是指向 unsigned char
或兼容类型的指针,也不是指向 void
的指针。所以不满足要求,编译器报错
指向unsigned char
的指针和指向数组的指针是不同的。如果pu
的类型是unsigned char *
,pa
的类型是unsigned char (*)[200]
(指向200个数组的指针unsigned char
),则[=1加1 =30=],与 pu + 1
一样,在 pu
之后生成指向下一个 unsigned char
的指针,但是向 pa
添加 1 会生成指向 [= 之后的下一个数组的指针32=]。换句话说,pu + 1
指向内存中的下一个字节,但 pa + 1
指向内存中更远的 200 个字节。
C 类型系统的一个目的是帮助避免错误。当 non-matching 类型被传递给一个函数时,程序员可能会期望一些不同于语言定义的行为。因此编译器发出诊断消息。
和memset
,它的第一个参数声明为void *
。 void
是一个不完整的类型;它充当其他类型的占位符。 memset
旨在处理任何对象的字节,因此它接受指向任何对象类型的指针。当为 void *
参数传递任何指向对象类型的指针时,它会自动转换为 void *
,没有任何诊断消息。
我试图将一个数组传递给一个方法。我尝试了以下方法:
- func2(ARRAY_NAME, length) => 有效,无警告
- func2(&ARRAY_NAME[0], length) => 有效,无警告
- func2(&ARRAY_NAME, length) => 有效,但有警告
我不明白为什么最后一个(#3)给出警告。 &ARRAY_NAME 在 memset、memcpy 等中工作时没有警告。为什么在自定义方法中出现问题?
警告信息:
functionTest.c:35:11: warning: passing argument 1 of ‘func2’ from incompatible pointer type [-Wincompatible-pointer-types]
35 | func2(&temp, ARRAY_SIZE);
| ^~~~~
| |
| unsigned char (*)[200]
functionTest.c:8:27: note: expected ‘unsigned char *’ but argument is of type ‘unsigned char (*)[200]’
8 | void func2(unsigned char* buf, int length)
代码
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#define ARRAY_SIZE 200
void func2(unsigned char* buf, int length)
{
// Change data of any index
buf[0] = 100;
buf[10] = 200;
}
void func1()
{
unsigned char temp[ARRAY_SIZE];
// Initialize
memset(temp, 0, sizeof(temp));
for(int i = 0; i < ARRAY_SIZE; i++)
{
printf("\t%d", temp[i]);
}
printf("\n-----------------------------------------------\n");
printf("Address : %p\n", &temp);
printf("Address of 0th index : %p\n", &temp[0]);
printf("\n-----------------------------------------------\n");
// Pass array in func2
func2(&temp, ARRAY_SIZE); // WARNING
func2(&temp[0], ARRAY_SIZE); // NO WARNING
for(int i = 0; i < ARRAY_SIZE; i++)
{
printf("\t%d", temp[i]);
}
printf("\n-----------------------------------------------\n");
}
int main()
{
func1();
return 0;
}
错误信息中写得很清楚
functionTest.c:8:27: note: expected ‘unsigned char *’ but argument is of type ‘unsigned char (*)[200]’
8 | void func2(unsigned char* buf, int length)
该函数需要一个类型为 unsigned char *
的指针,但参数表达式 &temp
的类型为 unsigned char ( * )[200]
并且没有从一种指针类型到另一种指针类型的隐式转换,尽管值为指针相同:数组占用内存范围的地址。
至于函数memset
和memcpy
则它们处理void *
类型的指针。例如,函数 memset
具有以下声明
void *memset(void *s, int c, size_t n);
指向其他类型对象的指针可以隐式转换为void *
类型的指针。
来自 C 标准(6.3.2.3 指针)
1 A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
func2
被声明为具有 unsigned char *
类型的第一个参数,因此应将其传递给与 unsigned char
兼容的类型的指针或指向 [=13= 的指针], 将自动转换为 unsigned char *
.
使用 func2(temp, ARRAY_SIZE)
,数组 temp
自动转换为指向其第一个元素的指针。这个指针是一个unsigned char *
,满足要求
对于func2(&temp[0], ARRAY_SIZE)
,temp[0]
是一个unsigned char
,所以&temp[0]
是一个指向unsigned char
的指针。这样就满足要求了。
和func2(&temp, ARRAY_SIZE)
一样,&temp
是指向unsigned char
的200个元素的数组的指针。它指向与&temp[0]
相同的位置,只是它的类型不同。它是一个指向数组的指针,而不是指向 unsigned char
或兼容类型的指针,也不是指向 void
的指针。所以不满足要求,编译器报错
指向unsigned char
的指针和指向数组的指针是不同的。如果pu
的类型是unsigned char *
,pa
的类型是unsigned char (*)[200]
(指向200个数组的指针unsigned char
),则[=1加1 =30=],与 pu + 1
一样,在 pu
之后生成指向下一个 unsigned char
的指针,但是向 pa
添加 1 会生成指向 [= 之后的下一个数组的指针32=]。换句话说,pu + 1
指向内存中的下一个字节,但 pa + 1
指向内存中更远的 200 个字节。
C 类型系统的一个目的是帮助避免错误。当 non-matching 类型被传递给一个函数时,程序员可能会期望一些不同于语言定义的行为。因此编译器发出诊断消息。
和memset
,它的第一个参数声明为void *
。 void
是一个不完整的类型;它充当其他类型的占位符。 memset
旨在处理任何对象的字节,因此它接受指向任何对象类型的指针。当为 void *
参数传递任何指向对象类型的指针时,它会自动转换为 void *
,没有任何诊断消息。