学习和学习。
#include <stdio.h>
#include <inttypes.h>
static void print_address0(const char *tag, const void *addr, const void *addr_1);
static void print_address1(const char *fmt, int i, const void *addr, const void *addr_1);
static void print_address2(const char *fmt, int i, int j, const void *addr, const void *addr_1);
#define ANALYZE_0(val) print_address0(#val, val, (val)+1)
#define ANALYZE_1(fmt, i, val) print_address1(fmt, i, val, (val)+1)
#define ANALYZE_2(fmt, i, j, val) print_address2(fmt, i, j, val, (val)+1)
int main(void)
{
int n[3][3] =
{
{ 2, 4, 3 },
{ 6, 8, 5 },
{ 3, 5, 1 },
};
ANALYZE_0(&n);
ANALYZE_0( n);
ANALYZE_0(*n);
for (int i = 0; i < 3; i++)
{
ANALYZE_1("*(n+%d)", i, *(n+i));
ANALYZE_1("n[%d]", i, n[i]);
ANALYZE_1("&n[%d]", i, &n[i]);
for (int j = 0; j < 3; j++)
ANALYZE_2("&n[%d][%d]", i, j, &n[i][j]);
}
return 0;
}
static void print_address0(const char *tag, const void *addr, const void *addr_1)
{
printf("%-8s = 0x%.8" PRIXPTR, tag, (uintptr_t)addr);
char buffer[16];
snprintf(buffer, sizeof(buffer), "(%s)+1", tag);
printf("; %-12s = 0x%.8" PRIXPTR "\n", buffer, (uintptr_t)addr_1);
}
static void print_address1(const char *fmt, int i, const void *addr, const void *addr_1)
{
char buffer[16];
snprintf(buffer, sizeof(buffer), fmt, i);
print_address0(buffer, addr, addr_1);
}
static void print_address2(const char *fmt, int i, int j, const void *addr, const void *addr_1)
{
char buffer[16];
snprintf(buffer, sizeof(buffer), fmt, i, j);
print_address0(buffer, addr, addr_1);
}
Mac OS X 10.8.3(64 位编译)上 GCC 4.7.1 的输出:
&n = 0x7FFF5F2D74C0; (&n)+1 = 0x7FFF5F2D74E4
n = 0x7FFF5F2D74C0; (n)+1 = 0x7FFF5F2D74CC
*n = 0x7FFF5F2D74C0; (*n)+1 = 0x7FFF5F2D74C4
*(n+0) = 0x7FFF5F2D74C0; (*(n+0))+1 = 0x7FFF5F2D74C4
n[0] = 0x7FFF5F2D74C0; (n[0])+1 = 0x7FFF5F2D74C4
&n[0] = 0x7FFF5F2D74C0; (&n[0])+1 = 0x7FFF5F2D74CC
&n[0][0] = 0x7FFF5F2D74C0; (&n[0][0])+1 = 0x7FFF5F2D74C4
&n[0][1] = 0x7FFF5F2D74C4; (&n[0][1])+1 = 0x7FFF5F2D74C8
&n[0][2] = 0x7FFF5F2D74C8; (&n[0][2])+1 = 0x7FFF5F2D74CC
*(n+1) = 0x7FFF5F2D74CC; (*(n+1))+1 = 0x7FFF5F2D74D0
n[1] = 0x7FFF5F2D74CC; (n[1])+1 = 0x7FFF5F2D74D0
&n[1] = 0x7FFF5F2D74CC; (&n[1])+1 = 0x7FFF5F2D74D8
&n[1][0] = 0x7FFF5F2D74CC; (&n[1][0])+1 = 0x7FFF5F2D74D0
&n[1][1] = 0x7FFF5F2D74D0; (&n[1][1])+1 = 0x7FFF5F2D74D4
&n[1][2] = 0x7FFF5F2D74D4; (&n[1][2])+1 = 0x7FFF5F2D74D8
*(n+2) = 0x7FFF5F2D74D8; (*(n+2))+1 = 0x7FFF5F2D74DC
n[2] = 0x7FFF5F2D74D8; (n[2])+1 = 0x7FFF5F2D74DC
&n[2] = 0x7FFF5F2D74D8; (&n[2])+1 = 0x7FFF5F2D74E4
&n[2][0] = 0x7FFF5F2D74D8; (&n[2][0])+1 = 0x7FFF5F2D74DC
&n[2][1] = 0x7FFF5F2D74DC; (&n[2][1])+1 = 0x7FFF5F2D74E0
&n[2][2] = 0x7FFF5F2D74E0; (&n[2][2])+1 = 0x7FFF5F2D74E4
输出显示了与数组元素关联的地址的许多变化。每行显示一个表达式的地址,以及同一个表达式的地址加一(差异表示指向的对象的大小,因此)。
代码使用宏封装重复的代码,使main()
程序更清晰。其他三个函数处理要打印的字符串和值的格式。代码有点复杂,但这样比没有函数编写更清晰(我试过了;正在分析的细节完全丢失在必要的代码中)。