我有一些旧代码,其中一个函数返回指向8个uint8_t数组的指针,另一个函数返回指向uint8_t的指向数组的指针。
typedef uint8_t (*u8_8)[8]; //hope this typedef pointer to array of 8 uint8
先说第一个实现如下
u8_8 get(void)
{
static uint8_t ar[8];
return &ar;
}
第二个函数使用uint8_t *并对其进行一些魔术处理
void second(uint8_t *data)
{
//...
}
我的问题是。我的转换正确吗?
//...
uint8_t *p = *(get());
second(p);
没有编译器警告,但我只是想确定一下。 感谢你并致以真诚的问候。 :)
答案 0 :(得分:0)
函数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());
答案 1 :(得分:0)
我的问题是。我的转换正确吗?
//...
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
答案 2 :(得分:0)
“ 我的转换正确吗?没有编译器警告,但我只是想确定一下。”
是的,一切都正确。没有语法错误,也没有调用未定义的行为,因为所有(指针)类型在各自的表达式中都匹配。
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]
与被调用函数&ar
中返回的get()
的类型匹配。
使用uint8_t
运算符解引用指向8 *(get())
*
数组的指针,类型uint8_t (*)[8]
获得uint8_t
,类型{的8个元素的数组{1}}。数组又一次衰减指向它的第一个元素的指针,键入uint8_t [8]
与调用者中的uint_8t *
完全匹配,因此分配是正确的。
p
second(p);
需要一个second
类型的参数,该参数与调用者中的uint8_t *
匹配。
您的代码可以简化为:
p
注意: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
现在已经完全没有必要并且是多余的,但是您需要将typedef uint8_t (*u8_8)[8];
的返回类型更改为get
,还需要更改的初始化。 uint8_t *
在呼叫者中。
如果您在调用方中不需要指针p
,甚至可以直接将p
的返回值用作get()
的参数:
second()