char contents[8][2]={"1","2","3","4","5","6","7","8"};
char* contentsx[8]={"1","2","3","4","5","6","7","8"};
printf("Contents: %sn", contents[1]);
printf("Contents: %sn", &contents[1]);
printf("Contentsx: %sn", contentsx[1]);
printf("Contentsx: %sn", &contentsx[1]);
打印:
Contents: 2
Contents: 2
Contentsx:2
Contentsx: //prints nothing or some garbage character
问题是,为什么contents[1]也就是元素1的值,输出与&contents[1]相同的结果,这是元素1的地址在这个上下文中,为什么contentsx[1]的值与&contentsx[1](有一些未定义的行为)这是因为contents
是数组的数组。
contents[1]
表示这个数组中的第二个数组。因此,它的名称衰变成指向第一个元素的指针,该元素的大小为1。而&contents[1]
则指向大小为2的整个数组。
xcontents[1]
是指向给定字符串的确切位置的char *
。&xcontents[1]
是指向条目的char **
,在本例中是char *
。
contents
数组是char
的8x2数组。它的元素是char[2]
——由2个char
组成的数组。因此,contents[1]
是索引为1
的char[2]
的数组。当你取该数组的地址时,它与该数组的初始元素的位置相同,即&contents[1][0]
,它与字符串"2"
的初始元素的位置相同。
虽然char[2]
的地址不是printf
'期望的%s
格式说明符,但在这种情况下它恰好有效,因为地址恰好匹配;但是,这被认为是未定义的行为。
当您在指针数组contentsx
上尝试同样的事情时,结果是不同的:现在您正在传递索引1
的指针的地址,该地址不再与字符串的位置一致,再次导致未定义行为。但是,这一次,未定义的行为表现为不打印任何内容,或者打印随机字符。