C语言 指向 N 个元素数组的指针与指向数组或数组的第一个元素的指针



我有一些遗留代码,其中一个函数返回指向 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());

相关内容

  • 没有找到相关文章

最新更新