sizeof(数组名)
1.括号内只有数组名,没有其他内容,即不对数组名进行运算 表示整个数组,sizeof(数组名)计算的是整个数组的大小,单位是字节
2. &数组名 &后面直接跟数组名 得到的是数组的地址 除了上面两种情况,数组名表示的都是数组首元素的地址
3.!!!数组的地址和数组首元素的地址的意义(区别)在,+1时才体现出来!!!!
strlen()
1.strlen() 求字符串的长度,遇到 \0 停止 ,\0 是停止的标志,不计入总字符串长度中 ()内放入地址 长度 字符串
2.”abcdef” 在双引号中,隐藏了一个字符 \0, 数组的地址 和 数组首元素的地址是相同, 但是因为数组中的元素 会在首元素地址的基础上,往后依次排列,所以数组的地址+1 和 数组首元素地址+1 所指向的不是同一份空间
- 整型数组
#include<string.h>
#include<stdio.h>
int main()
{
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a)); //16 sizeof() 数组名单独放在()内,求得是数组的大小,单位是字节。 数组有4个元素,每个元素都是整型,整型是4个字节
printf("%d\n", sizeof(a + 0)); //4 括号内不是单纯的数组名,对数组名+1 表示的是首元素的地址,首元素的地址 占4个字节
printf("%d\n", sizeof(*a)); //4 括号内除了数组名之外,还有别的操作符,所以括号内的数组名表示的不是整个数组,而是首元素的地址 *对数组名解引用,取出的是 首元素, 数组中的元素都是整型,所以是4字节
printf("%d\n", sizeof(a + 1)); //4 括号内除了数组名之外, 进行了+1操作,所以括号内的数组名表示的是首元素的地址,首元素地址+1 表示第二个元素的地址, 地址存放在指针中,故4个字节
printf("%d\n", sizeof(a[1])); //4 a[1] 表示第二个元素, 因为是整型数组,所以数组中的元素都是整型,故 4个字节
printf("%d\n", sizeof(&a)); //4 & 后面直接+数组名,表示的是整个数组的地址, 但是无论是首元素地址 还是 首元素的地址,都是地址 ,地址用指针接收,都是4个字节
printf("%d\n", sizeof(*&a)); //16 &后面直接跟数组名,取出的是 数组的地址, 对数组的地址解引用, 取出的是数组里面的内容,即整型的 1,2,3,4 故占16个字节
printf("%d\n", sizeof(&a + 1)); //4 &后面直接跟数组名, 取出的是 数组的地址, +1 表示跳过整个数组的地址,来到整个数组地址 的下一个地址,但是最终结果落脚到 地址 身上,所以地址的字节为4
printf("%d\n", sizeof(&a[0])); //4 []的优先级高于 & ,所以,取出第一个元素的地址,所以4字节
printf("%d\n", sizeof(&a[0] + 1));//4 优先级 [] > & > + , 表示的是取出第一个元素的地址,在第一个元素的地址的基础上+1, 即表示的是第二个元素的地址。 所以4字节
- 字符型数组
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr)); // 6 sizeof() 括号中只有数组名,表示的是整个数组的大小,虽然数组在下表引用符中没有定义元素个数,但是通过后面{} 可知道 元素个数有6个,有因为每个元素字符型,字符型占1个字节,所以大小是 6
printf("%d\n", sizeof(arr + 0)); //4 括号内除了数组名还有 +0,所以表示得是 首元素的地址,地址在32位平台上占4个字节
printf("%d\n", sizeof(*arr)); //1 括号内除了数组名还有别的操作符 * ,所以数组名表示的是首元素的地址,对首元素的地址解引用,取出第一个元素,因为是字符型数组,所以首元素是字符,占1个字节
printf("%d\n", sizeof(arr[1])); //1 表示第二个元素,字符型元素,所以占1个字节
printf("%d\n", sizeof(&arr)); //4 &后面直接跟数组名,表示的是整个数组的地址,地址在32位平台上占4个字节
printf("%d\n", sizeof(&arr + 1)); //4 取出整个数组的地址,地址+1,结果仍是地址,故4个字节
printf("%d\n", sizeof(&arr[0] + 1)); //4 取出第一个元素的地址,地址在+1,故4个字节
printf("%d\n", strlen(arr)); //随机值 strlrn() 遇到\0 才会停止,题目上是字符型数组,每个元素都占1个字节,并且元素中没有\0 所以相当于数组大小未定义,会一直寻找,直到 遇见\0, 才停止,其间一共找了多少个元素,随机。
printf("%d\n", strlen(arr + 0)); //随机值 首元素的地址,依据首元素的地址向后寻找,一直找到\0停止, 所以是随机值
// printf("%d\n", strlen(*arr)); //err(错误) ??//*arr? strlen() 是根据地址查找字符串长度的,*对数组名解引用结果拿到的是元素内容,是个值。strlen 就把97 当做是地址进行访问,造成了访问冲突。
// printf("%d\n", strlen(arr[1])); //err 原因同上
printf("%d\n", strlen(&arr)); //随机值 拿出整个数组的地址,也相当于拿出首元素的地址,所以往后寻找\0,故随机值
printf("%d\n", strlen(&arr + 1)); //随机值,但是比strlen(&arr) 小6 因为(&arr + 1),是跳过整个数组,来到元素'f' 后面的地址
printf("%d\n", strlen(&arr[0] + 1)); //随机值 先得到a的地址, 再+1, 得到b的地址,根据b的地址向后寻找,一直找到\0停止, 所以是随机值
char arr[] = "abcdef";
printf("%d\n", sizeof(arr)); // 答案不是4,答案是7!!! 4 括号中 只有数组名,表示的是整个数组的地址,地址的大小是4个字节 /*7 sizeof()计算 括号中的类型或者变量的大小,与是否遇到 \0 无关,"abcdef"中隐藏了字符串结束的标志,即 \0,转义字符\0 算一个字符,所以 数组中一共有7个元素,因为每个元素都是字符型的,所以 大小为7 字节*/
printf("%d\n", sizeof(arr + 0)); //4 括号中 除了数组名 还有运算+1 所以表示的是首元素的地址,首元素的地址+1,仍然是首元素的地址,故是4个字节
printf("%d\n", sizeof(*arr)); //1 括号中 除了数组名 还有操作符* 所以是arr 表示的是首元素的地址, 对首元素地址解引用。拿出的是第一个元素,因为是字符型数组,所以,元素占1个字节
printf("%d\n", sizeof(arr[1])); //1 取出第二个元素,元素是字符型的,所以是1个字节
printf("%d\n", sizeof(&arr)); //4 &后面直接跟数组名,取出的是整个数组的地址,地址占4个字节
printf("%d\n", sizeof(&arr + 1)); //4 &后面直接跟数组名,取出整个数组的地址,整个数组的地址+1,则跳过这个数组,来到数组最后一个元素 后面所指向的地址
printf("%d\n", sizeof(&arr[0] + 1)); //4 不是&后面直接跟数组名的情况(arr[0]不是数组名!),最终结果是第二个元素的地址,故4个字节
printf("%d\n", strlen(arr)); //6 拿到整个数组的地址,"abcdef"中隐藏了字符串结束的标志,即 \0, 遇到\0就停止,所以字符串的长度是6
printf("%d\n", strlen(arr + 0)); //6 拿到首元素地址
// printf("%d\n", strlen(*arr)); //err 数组名不是单独放在()中的还有操作符,所以数组名表示的是首元素的地址,对首元素地址地址进行解引用,得到a,a表示的是值97,所以错误
// printf("%d\n", strlen(arr[1])); //err 拿到第二个元素b,代表值98
printf("%d\n", strlen(&arr)); //6 取出数组的地址,也就是首元素的地址,依次往后查找,所以长度是6
printf("%d\n", strlen(&arr + 1)); //随机值 &后面直接跟数组名,所以取出的是整个数组的地址,整个数组的地址+1,来到整个数组的后面的一个地址,因为不知道地址的内容,所以不确定何时能遇到\0,故是随机值
printf("%d\n", strlen(&arr[0] + 1)); //5 &后面不是 不是直接跟数组名, 所以取出的是第一个元素的地址,地址再+1, 取出第二个元素的地址,向后查找,故长度是5
- 指针类型
char *p = "abcdef"; //指针变量p,p里面存的是是首元素的地址(存的不是abcdef!!!),就说通过p指向首元素
printf("%d\n", sizeof(p)); //4 p是个指针变量,指向首元素的地址,32位平台上是4个字节
printf("%d\n", sizeof(p + 1)); //4 p指向首元素的地址 +1 则指向第二个元素的地址
printf("%d\n", sizeof(*p)); //1 p指向首元素地址,解引用的结果是字符a
printf("%d\n", sizeof(p[0])); //1 等价于 *(p+0),指向第一个元素,元素a的字节是1
printf("%d\n", sizeof(&p)); //4 p是指针变量,能把别的变量的地址放到自己的内容里面,对&p 是把p自身的地址取出来,故4个字节
printf("%d\n", sizeof(&p + 1)); //4 !!指向p的空间的下属空间,即跳过4个字节后的内容的地址
printf("%d\n", sizeof(&p[0] + 1)); //4 p[0] 得到的是 元素a, 在对元素a取地址,然后+1 得到的仍然是地址,是元素b对应的地址
printf("%d\n", strlen(p)); //6 p是指针变量 存储的内容是字符串的 首字符的地址,strlen()根据地址一直往后数,遇到\0停止
printf("%d\n", strlen(p + 1)); //5 从b开始数
//printf("%d\n", strlen(*p)); //err 括号中是具体的值,而不是地址,会发生访问冲突
//printf("%d\n", strlen(p[0])); //err 理由同上
printf("%d\n", strlen(&p)); //随机值 从p的地址开始向后面数,直到遇到\0
printf("%d\n", strlen(&p + 1)); //随机值
printf("%d\n", strlen(&p[0] + 1)); //5 对第一个元素去地址 再+1得到 b的地址,然后往后数
- 二维数组
int a[3][4] = { 0 }; //将二维数组想象成一个一位数组,首元素就是第一行,二维数组有几行,对应一维数组就有几个元素
//对于二维数组来说,数组名如果不是单独放在括号中的话,会降级 比如说sizeof(arr)->单独放在括号内,表示的是整个二维数组; sizeof(arr+1)->数组名不是单独放在括号内,表示的是第一行的数组+1,即第二行的数组;
//sizeof(arr[0])->数组名(把一行当做是一个元素,arr[1]表示二维数组的第二行,看做第二个元素,arr[3]表示二维数组的第三行,看做第三个元素),单独放在括号里,表示的是二维数组的第1行; sizeof(a[0]+1)-> 数组名不是单独放在括号内,所以 由第一行的地址 变成第一行的第一个元素的地址,+1 表示第一行第二个元素的地址。 1
printf("%d\n", sizeof(a)); //48 数组名单独放在括号内 ,表示整个数组 整个数组 有12个i 整型元素
printf("%d\n", sizeof(a[0][0])); //4 第一行第一个元素
printf("%d\n", sizeof(a[0])); //16 第一行的数组名 ,单独放在括号里表示第一行的所有元素
printf("%d\n", sizeof(a[0] + 1)); //4 第一行的数组名,没有单独放在括号中,第一行第一个元素的地址
printf("%d\n", sizeof(a + 1)); //4 数组名没有单独放在括号内,要降级,表示第一行的地址,第一行的地址+1,表示第二行的第二行的地址。
printf("%d\n", sizeof(&a[0] + 1)); //4 对第一行取地址,地址+1 表示第一行第二个元素的地址
printf("%d\n", sizeof(*a)); //16 !!数组名没有单独放在括号中,在一维数组表示首元素的地址,在二维数组中表示一整行的地址。 对第一行的地址解引用,就是第一行的内容
printf("%d\n", sizeof(a[3])); //16 表示第四行,二维数组中没有第四行的内容,但是因为操作符sizeof(),是在编译阶段进行的,程序并没有到达执行阶段,所以只是判断过程。一行有4个元素,故16字节
system("pause");
return 0;
}