typedef short int (SPTR) [2];
SPTR *p,*q;
如何解释p和q。?
此外,问题是:
char a2D[5][3] =
{
{ 1, 2, 3},
{ 4, 5, 6},
{ 7, 8, 9},
{10, 11, 12},
{13, 14, 15}
};
p = q = (short int (*)[2])a2D[1];
printf("%X %X\n", (*++p)[1], (q[1])[2]);
有人可以帮助我理解代码的行为......
答案 0 :(得分:4)
SPTR
是“Array of 2 shorts”的别名。因此,SPTR *
与“指向2个短裤数组的指针”相同,即short int (*)[2]
。
同样,p
和q
是指向2个短裤数组的指针。
代码正在挑选一个二维chars数组并将其第二个位置(a2D[1]
)解释为由p
和q
指向的2个短裤的数组。换句话说,这个3个字符的数组:
{ 4, 5, 6 }
被解释为短数组,p
和q
都指向它。由于p
是指向2个短片数组的指针,因此递增p
将使其前进sizeof(short)*2
个位置。为什么?好吧,递增p
与指向2个短裤的下一个数组相同,即sizeof(short)*2
个字节。
假设8位字符和16位短路,(*++p)[1]
将p
增加32位,所以现在p
指向子数组{ 8, 9 }
(这是++p
)的效果。然后,我们取消引用p
,这意味着“在该位置选择数组”。现在,我们有一个数组索引运算符,您可以将其视为向*p
的新值添加1((*p)+1
将指向{10, 11, 12}
,请记住它前进16位因为这是短数组中每个元素的大小),然后解除引用。因为这被解释为short,所以取消引用实际上会同时读取10
和11
,因为我们之前假设每个char都是8位。因此,p
“认为”他正在读短片,所以将读取16位(2个字符)。
现在,发生的事情取决于您的机器是小端还是大端。如果它打印B0A
,那么它是小端,因为它将10
解释为最不重要的字节。否则,它是大端。
可以使用相同的方法来了解(q[1])[2]
会发生什么,这与q[1][2]
相同。可以将其视为*(*(q+1)+2)
:q+1
指向8
。向*(q+1)
添加2然后解除引用它与在位置2中索引短路数组相同,因此您将获得在此之后存储的32位的任何内容,即12
。这与以前一样,取决于您的机器的字节顺序。它会打印C0D
或D0C
。
答案 1 :(得分:2)
p
和q
?typedef short int (SPTR) [2]; //Have brackets around SPTR or not. Its the same.
SPTR
实例的类型为short int [2]
。
SPTR *p, *q;
p
和q
的类型为short int (*) [2]
由于您使用p
和q
来保存a2D
中元素的地址,因此SPTR
typedef'很好
如
typedef char SPTR [2];
后来,
p = q = (char (*)[2])a2D[1]; // Assigns p & q to point to element '4' in a2D array
printf("%X %X\n", (*++p)[1], (q[1])[2]);
如上所述,p
指向大小为2的char
数组。
*p
为您提供数组第一个元素的地址。
对于char a[2]
,a
为您提供数组第一个元素的地址,a[0]
或*(a+0)
为您提供第一个元素的值数组。
同样在这种情况下,(*p)[0]
或*((*p)+0)
会为您提供p
指向的数组的第一个元素。在您的情况下,它将是4
。与q
相同,因为它们都拥有相同的地址。
(*p)[1]
为您提供p
在表达式(*++p)
中,p增加1
。这是指针算术,1
被缩放到p
指向的数据类型的大小。因此,p
增加2 * sizeof (char)
,现在指向6
。
(*++p)[0]
为您提供6
。在你的情况下,它是(*++p)[1]
,所以它给你7.
q[1][1]
与(*(q+1))[1]
类似。按q
增加1
。 p
提到的相同指针算法也适用q
。而且,现在p
和q
都指向同一地址。因此q[1][1]
也会为您提供7
。
q[1][2]
是q[1][1]
旁边的一个字符,因此会给您8
注意:
a
的类型为pointer-to-char
p
的类型为pointer-to-array-of-2-chars
两者的类型不同。我之前提到过a
,只是为了轻松理解涉及*p