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

Pointer arithmetic of unspecified type with known size

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] 类型的变量,这样我就不必每次都在该指针上执行指针算术时进行强制转换?

这种行为是否可移植?

你的意思好像是下面这样

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 

你是什么意思? ptr 甚至没有分配。转换它会导致未定义的行为。

您可以这样做

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

或者这个

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

Pointer arithmetic of unspecified type with known size

And is this behavior even portable?

严格来说:可能:

需要深入了解 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 * 可能比通常预期的更加不同 - 即使这种差异在今天非常罕见。