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

时间:2020-06-18 17:40:30

标签: c pointers implicit-conversion return-type function-declaration

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

没有编译器警告,但我只是想确定一下。 感谢你并致以真诚的问候。 :)

3 个答案:

答案 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()