我有一些遗留代码,其中一个函数返回指向 8 个uint8_t数组的指针,另一个函数获取指向指向数组uint8_t的指针。
typedef uint8_t (*u8_8)[8]; //hope this typedef pointer to array of 8 uint8
假设 first 的实现如下
u8_8 get(void)
{
static uint8_t ar[8];
return &ar;
}
第二个函数采用 uint8_t * 并用它做一些魔术
void second(uint8_t *data)
{
//...
}
我的问题是。我的转换是否正确?
//...
uint8_t *p = *(get());
second(p);
没有编译器警告,但我只是想确定一下。 谢谢你,最诚挚的问候。:)
函数get
返回指向8
无符号字节数组的指针。
如果取消引用此指针,则会得到它指向的数组。
这个数组将依次衰减到一个指针(到uint8_t
,即uint8_t *
(。
这正是second
函数所期望的。
事实上,你可以将整个事情缩短为一个语句:
second(*get());
话虽如此,get
实际上没有必要返回指向数组的指针。相反,它可以返回数组本身,让它衰减到指向其第一个元素的指针:
uint8_t *get()
{
static uint8_t ar[8];
return ar;
}
...
uint8_t *o = get();
second(p);
// Or: second(get());
我的问题是。我的转换是否正确?
//...
uint8_t *p = *(get());
second(p);
转换是有效的,因为表达式 *(get((( 具有uint8_t [8]
类型,并用作初始值设定项,它被转换为指向指向数组的第一个元素的指针。
从函数返回uint8_t (*u8_8)[8]
类型的对象而不是uint8_t *
类型的对象确实有意义,因为您可以确定指向数组的元素数。也就是说,实际上函数返回提供了两种信息:数组的地址和数组中元素的数量。
例如,如果你有一个声明为
void func( uint8_t *a, size_t n );
然后你可以轻松地从函数中调用它来调用返回的指向数组 get like
u8_8 ptr = get();
func( *ptr, sizeof( *ptr ) / sizeof( **ptr ) );
这是一个演示程序。
#include <stdio.h>
#include <stdint.h>
typedef uint8_t (*u8_8)[8];
u8_8 get(void)
{
static uint8_t ar[8] = "12345678";
return &ar;
}
void out( const uint8_t *a, size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
putchar( a[i] );
}
putchar( 'n' );
}
int main(void)
{
u8_8 ptr = get();
out( *ptr, sizeof( *ptr ) / sizeof( **ptr ) );
return 0;
}
它的输出是
12345678
">我的转换正确吗?没有编译器警告,但我只是想确定一下。
是的,一切都是正确的。没有语法错误,也没有调用未定义的行为,因为所有(指针(类型在各自的表达式中都匹配。
u8_8 get(void)
{
static uint8_t ar[8];
return &ar;
}
return &ar;
&ar
具有类型uint8_t (*)[8]
。请注意,当您使用return ar;
时,ar
会衰减到指向其第一个元素的指针,键入uint8_t *
;但是由于&
运算符应用于它,因此不会以这种方式发生。相反,它获得指向整个数组uint8_t (*)[8]
的指针。
*(get())
表达式get()
的类型uint8_t (*)[8]
与被调用函数get()
中返回的&ar
的类型匹配。
使用*
运算符取消引用指向 8 个uint8_t
*(get())
数组的指针,类型uint8_t (*)[8]
获得一个包含 8 个元素的数组uint8_t
,类型uint8_t [8]
。数组再次衰减到指针指向它的第一个元素,键入uint_8t *
与调用者中的p
完全匹配,因此分配是正确的。
second(p);
second
需要与调用方中的p
匹配的类型为uint8_t *
的参数。
您的代码可以简化为:
uint8_t* get (void)
{
static uint8_t ar[8];
return ar;
}
void second (uint8_t *data)
{
//...
}
....
int main (void)
{
uint8_t *p = get();
second(p);
}
注意:typedef uint8_t (*u8_8)[8];
的typedef
现在完全不必要和冗余,但您需要将get
的返回类型更改为uint8_t *
,并相应地更改调用方中p
的初始化。
如果你不需要调用者中的指针p
,你甚至可以直接使用get()
的返回值作为参数来second()
:
second(get());