已知大小的未指定类型的指针算术

问题描述 投票:-5回答:4
void * ptr = NULL; // array of unspecified 13-byte type

for (int i = 0; i < 10; i++) {
    printf("%i ", ((char (*) [13]) ptr) + i);
}

putchar('\n');

输出:

0 13 26 39 52 65 78 91 104 117

所以这有效(至少在GCC上有效,但是如何声明类型为(char (*) [13]的变量,这样我每次想对该指针执行指针算术时就不必强制转换?

这种行为甚至可以移植吗?

c void-pointers pointer-arithmetic
4个回答
1
投票

已知大小的未指定类型的指针算术

这种行为甚至可以移植吗?

严格:也许:

需要深入研究C17 6.3.2.3 Pointers

如下所示,取决于&fred[0]的值是否能够毫无问题地转换为ptr。许多实现都可以毫无问题地处理此问题,但是ptr是指向数组的指针,而不是指向char的指针。如果ptr是指向char的指针,没问题。

思考,因为ptrfred都具有相同的对齐要求-代码正常。

typedef something unspecified_13_byte_type;
assert(sizeof(unspecified_13_byte_type) == 13);

#define N
unspecified_13_byte_type fred[N];

char (*ptr)[13] = (void *) fred;
for (int i = 0; i < N; i++) {
  // printf("%i ", ((char (*) [13]) ptr) + i);
  printf("%p ", (void *)  (((char (*) [13]) ptr) + i));
}
puts("");

更深:如果something是某个struct,则ptr&fred[0]不必使用相同的编码,甚至不必使用相同的大小-即使它们彼此之间可以很好地相互转换并等同。 struct指针和char *可能比通常预期的要大得多-即使今天这种差异非常罕见。


0
投票

你是什么意思? ptr甚至都没有分配。强制转换将导致不确定的行为。

您可以执行此操作

void * ptr = malloc(10 * 13); // on heap

或此

void * ptr = (char [10][13]){}; // on stack (C99)

0
投票

似乎您的意思是以下内容

char s[10][13];
//…
void * ptr = s;

用作初始化程序的数组s被隐式转换为指向类型为char ( * )[13]的第一个元素的指针。

或者你可以写

char s[10][13];
//…
char ( *tmp )[13] = s;
void * ptr = tmp;

这里是一个演示程序,显示了指针算法

#include <stdio.h>

int main(void) 
{
    enum { N = 13 };
    char s[][N] = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" };
    const size_t M = sizeof( s ) / sizeof( *s );

    void * ptr = s; 

    for ( size_t i = 0; i < M; i++ )
    {
        printf( "%s ", ( ( char ( * )[N] )ptr )[i] );
        // or
        // printf( "%s ", *( ( char ( * )[N] )ptr + i ) );
    }

    putchar( '\n' );

    return 0;
}

其输出为

A B C D E F G H I J 

0
投票

结果就是这个

char (*another_ptr)[13] = ptr;

Source

© www.soinside.com 2019 - 2024. All rights reserved.