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]
的变量,这样我每次想对该指针执行指针算术时就不必强制转换?
这种行为甚至可以移植吗?
已知大小的未指定类型的指针算术
这种行为甚至可以移植吗?
严格:也许:
需要深入研究C17 6.3.2.3 Pointers
如下所示,取决于&fred[0]
的值是否能够毫无问题地转换为ptr
。许多实现都可以毫无问题地处理此问题,但是ptr
是指向数组的指针,而不是指向char
的指针。如果ptr
是指向char
的指针,没问题。
我思考,因为ptr
和fred
都具有相同的对齐要求-代码正常。
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 *
可能比通常预期的要大得多-即使今天这种差异非常罕见。
你是什么意思? ptr
甚至都没有分配。强制转换将导致不确定的行为。
您可以执行此操作
void * ptr = malloc(10 * 13); // on heap
或此
void * ptr = (char [10][13]){}; // on stack (C99)
似乎您的意思是以下内容
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