typedef char trgm[3];
char test[2][3] = {'a','b','c','d','e','f'};
int main(void)
{
trgm *t;
t = test;
printf("%c\n",*(char *)t);
printf("%c\n",*(char *)*t);
printf("%c\n",**t);
return 0;
}
三个printf的输出相同。我不明白为什么t和* t相同?编译器内部做了什么?
答案 0 :(得分:0)
对同一个值有三种解释路径 - 数组占用的内存范围的起始地址。因此,取消引用转换为char *
的值,您将获得数组char
类型的第一个元素的值。
答案 1 :(得分:0)
您可以将数组变量视为包含其第一个元素的内存地址。在你的情况下,由于数组是一个2D数组,“第一个元素”t [0]实际上是指向“第一行”的指针。请注意,就内存而言,元素t [0]和t [1]没有特殊的存储空间,它会被转换为适当的内存偏移量,但这有助于这样思考。因此,当您使用指针(* t)时,您将获得与数组变量相同的值。
t = [0] --> 'a','b','c'
[1] --> 'd','e','f'
试试这个printf("%p %p %p\n", t,*t, t[0]);
,您将获得相同的价值。
答案 2 :(得分:0)
当您声明typedef char trgm[3];
时,trgm
引用* char [3]`数组。这很重要。
当您声明trgm *t = test
时,指针t
是指向char [3] 数组的指针。通过设置t = test;
,您可以使t
指向test
的第一个行(基本上等同于test[0]
。由于数组变量成立(或指向)test
的第一个元素,t
和test
都指向相同的值。取消指针t
或test
(例如*t
或*test
)将访问test
的第一个元素。
由于t
是指向char [3]数组的指针,因此它是一个具有两级间接的指针,因此可以解除引用两次(可以测试)。拿test[row][col]
。让我们看看数组的等效指针。 test can be written as
*(*(test + col) + row)
(col
和row
在引用第一个元素(例如0
)时都是test[0][0]
,所以上面只是
*(*(test + 0) + 0)
注意:加上0
的任何内容都是这样的,所以它简化为:
**test
t
只是:
(*t)[col] /* to index cols 0 - 2 */
它也可以改写为:
*((*t) + col)
第一个元素的col
为零,你得到
**t
但是,t
通过指向第一行,允许指针算术(例如t = t + 1;
或仅t++
)更新t
以指向第二行,等等。
总而言之,无论您是在查看test
还是在查看t
,最初都会引用test
中第一个元素的地址,两者都是(或者可以被认为是具有两个间接级别的指针,并且每次取消引用一次或两次仍将指向测试中的原始元素。您可以使用t
访问数组中的所有值,例如:
for (; t < &test[2]; t++)
printf (" %c, %c, %c\n", (*t)[0], (*t)[1], (*t)[2]);
putchar ('\n');
将输出:
a, b, c
d, e, f
最后,没有必要使test
成为全局变量。避免使用全局变量来减少名称冲突的可能性。在test
中声明main()
并将其指针传递给它所需的任何其他函数。
完全可以这样做,你可以这样做:
#include <stdio.h>
typedef char trgm[3];
int main(void)
{
char test[][3] = {{'a','b','c'},
{'d','e','f'}};
trgm *t;
t = test;
printf("%c\n",*(char *)t);
printf("%c\n",*(char *)*t);
printf("%c\n",**t);
for (; t < &test[2]; t++)
printf (" %c, %c, %c\n", (*t)[0], (*t)[1], (*t)[2]);
putchar ('\n');
return 0;
}
示例使用/输出
$ ./bin/p2x3
a
a
a
a, b, c
d, e, f
仔细看看,如果您有任何其他问题,请告诉我。