数组名的理解

一:一维数组int a[5]

数组名a代表数组首元素的地址,其类型为int *类型.
注意:和sizeof搭配使用,a表示整个数组整体,sizeof(a) = 5 * 4.

&a:
对一维数组名取地址,其指向整个数组,所以其类型为int (*)[5],指向整个一维数组的指针,如果你将它赋值给一个指针变量时只能赋值给一个 int(*p)[5];否则一般的编译器都会给出警告.所以sizeof(&a) = 4.

*a:
对数组第0个元素的解引用,就是a[0],所以sizeof(*a) = 1 * 4.

补充:对 a,&a 用%p打印,得到的值是相同的,因为它们所指向的空间的起始地址是相同的,但是它们所指向的空间大小不同.

二:二维数组名 int b[3][4]
数组名b代表数组首元素的地址,但是这里的首元素地址指的是第0行一维数组的地址,b = &b[0],其类型为int (*)[4],表示指向一维数组的指针.
注意:和sizeof搭配使用,a表示整个数组整体,sizeof(b) = 3 * 4 * 4.

&b:
对二维数组名取地址,其指向整个数组(对数组名使用&得到指向范围更大的指针),所以其类型为int (*)[3][4],但本身仍是一个指针,sizeof(&b) = 4,
&b指向整个二维数组,所以&b+1表示指向下个二维数组

*b:难点
b是指向一维数组的指针,对于二维数组而言这个一个行指针,解引用*一下表示列指针(对数组名使用*得到指向范围更小的指针),指向二维数组的单个元素,所以*b的本质上也是个指针,其类型int *.
但是当与sizeof搭配使用时,表示一维数组本身,可以这样理解:
b是指向一维数组的指针,*b就表示这个一维数组本身,所以sizeo(*b) = 4 * 4;b[0]:表示指向第0行的一维数组的数组名,所以b[0]指向这个一维数组首元素b[0][0]b[0] = *(b + 0) = *b, b表示指向第0行数组的行指针,*(b + 0)对行指针解引用为列指针,表示指向第0行第0列的元素的指针,其指针类型为int *.反过来&b[0] = b + 0,对列指针&为行指针(对数组指针&得到范围更大的指针)但是sizeof(b[0]) == 4 * 4,  b[0]表示第0行的一维数组名,对数组名用sizeof表示一维数组整体的大小


补充:

对 b,&b,  *b 用%p打印,得到的值是相同的,因为它们所指向的空间的起始地址是相同的,但是它们所指向的空间大小不同.


例题:

#include <stdio.h>
#include <string.h>

int main(void)
{    char a[3][20] = {0};
	strcpy(a[0], "hello");
	strcpy(a[1], "world");
	printf("%d\n", sizeof(&a)); //4
	printf("%d\n", sizeof(a)); //60
	printf("%d\n", sizeof(*a)); //20 * 1  //a为一维数组 20
	printf("%c\n", *(*a + 1));  //e
	printf("%s\n", *(a + 1));  //world
	printf("%d\n", sizeof('s')); //4

	return 0;
}

int main(void)
{
	char a[2][3] = { {0, 1, 2}, {3, 4, 5}};
	int b[3] = {10, 11, 12};
	//char c[2][3] = {{'a','b','c'},{'d','e','f'}};
	printf("%d\n", sizeof(&b)); //4
	printf("%d\n", sizeof(&a)); //4
	printf("%d\n", sizeof(a));  //6
	printf("%d\n", sizeof(*a)); //3
	printf("%c\n", *(*a + 1));  //显示乱码,因为字符数组存放的是整数,所以不能用%c打印,要用%d
	printf("%s\n", *(a + 1));   //显示乱码,因为字符数组存放的是整数,所以不能用%s打印 ,只有存放的是字符才可以这样使用
	//printf("%d\n", sizeof('s')); //4
	
	return 0;
}

int main(void)
{
    int a[2][3] = { {0, 1, 2}, {3, 4, 5}};
    int b[3] = {10, 11, 12};

    printf("%d\n", sizeof(&b)); //4
    printf("%d\n", sizeof(&a)); //4
    printf("%d\n", sizeof(a));  //4 * 6
    printf("%d\n", sizeof(*a)); //3 * 4
    printf("%d\n", sizeof(b)); //3 * 4
    printf("%d\n", sizeof(*b)); //1 * 4
    printf("\n");
    printf("%d\n", sizeof(a[0])); //3 *4
    printf("%d\n", *a[0]);  //0
#if 0
    printf("%p\n", a);
    printf("%p\n", &a);
    printf("%p\n", *a);
    printf("%p\n", b);
    printf("%p\n", &b);
#endif
    printf("%d\n", (**(&a + 1))[-1]); //&a + 1指向下个二维数组,(&a + 1))[-1]往上移动移动一个地址,得到的是指向起始地址空间内容为5,大小为二维数组大小的空间
									  //解引用*一下得到的是指向起始地址空间内容为5,大小为一维数组大小的空间,再解引用*一下得到的就是指向起始地址空间内容为,大小为一个元素大小的空间
    
    
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值