数组、字符数组、字符串与指针之间的转换并求sizeof和strlen 实例解释

 

 1.一维数组转换指针求 sizeof

int a[] = {1, 2, 3, 4};  //四个元素的一维数组

 以下严格按照一行代码,再加一行解释的格式来书写

printf ("%d", sizeof(a));  //16

   ① szieof (a),a为数组名,此时取整个数组的长度,四个元素,每个元素占四个字节。

printf ("%d", sizeof(a + 0));   //4

    ② szieof (a + 0),此时数组名 + -  数字(a + 1或 a - 1)就转换为指针,此处int型指针的长度为 4

 printf ("%d\n", sizeof(*a));   //4

    ③ sizeof (*a), 此时  *a ,对数组名解引用,转换为指向首元素的指针相当于a[0], 即数字 1 ,int型长度为4

printf ("%d\n", sizeof(a + 1));   //4  

     ④ 此时sizeof(a + 1)和上面sizeof(a + 0)一样,为 int 型指针

printf ("%d\n", sizeof(a[1]));   //4

     ⑤ a[1] 指向 数字 2,整型取sizeof 长度为 4

printf ("%d\n", sizeof(&a));   //4

     ⑥ 数组名取地址(&a)为整个数组a的地址,  转换为数组指针,指针类型长度为4

printf ("%d\n", sizeof(*&a));   //16

      ⑦ &a 为指向整个数组的指针, *&a  解引用,向当于求整个数组的长度

printf ("%d\n", sizeof(&a + 1));   //4

      ⑧ &a 为指向整个数组的指针, (&a + 1)指针加一还是指针,int型指针长度为4

printf ("%d\n", &a[0]);    //4

     ⑨ a[0]  取数组的首元素,&a[0]  为指向首元素的地址,为 int* 型 长度为四个字节    

printf ("%d\n", &a[0] + 1);     //4

    ⑩ &a[0] 为指向首元素的指针(int*), 指针加一还是指针

 

 2.字符数组,数组名指针转换求 sizeof  和  strlen

char arr[] = {'a' ,'b' , 'c', 'd', 'e', 'f'};  //初始化长度为6的字符数组

 以下严格按照一行代码,再加一行解释的格式来书写

求sizeof

printf ("%d\n", sizeof(arr));   //6

    ① arr为字符数组名,取sizeof 为整个字符数组的长度,6个元素每个元素占一个字节。

printf ("%d\n", sizeof(arr + 0));   //4

    ② (arr + 0)数组名+数字,转换为指针, 占4个字节。

printf ("%d\n", sizeof(*arr));   //1

    ③ (*arr)数组名解引用,取到数组首元素 arr[0],字符'a',char型长度为1。

printf ("%d\n", sizeof(arr[1]));   //1

    ④ arr[1] 取到数组第二个元素,字符 'b' ,长度为1个字节。

printf ("%d\n", sizeof(&arr));   //4

    ⑤ &arr 数组名取地址,转换为指针(数组指针), 长度为 4 字节。

printf ("%d\n", sizeof(&arr + 1));   //4

    ⑥ &arr + 1 ,指针(数组指针) + 或 - 数字,还是指针,长度为4。

printf ("%d\n", sizeof(&arr[0] + 1));   //4

    ⑦ arr[0] 为char型,&arr[0] 再取地址为 char* 型指针,char* + 1 还是指针 ,占4个字节。

求strlen

printf ("%d\n", strlen(arr));  
printf ("%d\n", strlen(arr + 0)); 
printf ("%d\n", strlen(*arr)); 
printf ("%d\n", strlen(arr[1]));             //未定义行为
printf ("%d\n", strlen(&arr)); 
printf ("%d\n", strlen(&arr + 1)); 
printf ("%d\n", strlen(&arr[0] + 1)); 

    上面这串代码,对字符数组求  strlen,为非法行为(编译常说的未定义行为),这种操作在其他语言中是无法编译通过的。 因为strlen操作中,必须以读到 '\0' 来作为函数判断结束,字符数组并不是字符串以反杠零结尾。

 

3. 字符数组指向字符串,数组名指针转换,求 sizeof 和 strlen

char arr[] = "abcdef";  //字符数组指向长度为6的字符串

  以下严格按照一行代码,再加一行解释的格式来书写

  求sizeof

printf ("%d\n", sizeof(arr));    //7

    ① arr 数组名 求sizeof,为求整个字符串的长度,字符串以 '\0' 结尾,所以char型长度为 7。

printf ("%d\n", sizeof(arr + 0));    //4

    ② (arr + 0)数组名+数字,转换为指针, 占4个字节。

printf ("%d\n", sizeof(*arr));    //1

    ③(*arr)数组名解引用,取到数组首元素 arr[0],字符'a',char型长度为1。

printf ("%d\n", sizeof(arr[1]));    //1

    ④ arr[1] 取字符串第二个元素 'b' ,char型长度为1。

printf ("%d\n", sizeof(&arr));    //4

    ⑤ &arr 数组名取地址,转换为指针(数组指针), 长度为 4 字节。

printf ("%d\n", sizeof(&arr + 1));     //4

    ⑥ &arr + 1 ,指针(数组指针) + 或 - 数字,还是指针,长度为4。

printf ("%d\n", sizeof(&arr + 1));     //4

    ⑦ arr[0] 为char型,&arr[0] 再取地址为 char* 型指针,char* + 1 还是指针 ,占4个字节。

求strlen

printf ("%d\n", strlen(arr));   //6

    ① 字符串求 strlen ,从首元素 读到 '\0' 结束。长度为 6

printf ("%d\n", strlen(arr + 0));   //6

    ② 数组名 + 或 - 数字,转换为指向这个元素的指针,此时指向首元素的指针,从此处往后找,到 '\0' 位置处结束

                ① 和 ②在作用上是一致的。

printf ("%d\n", strlen(*arr));   //未定义行为

    ③ (*arr)数组名解引用,取到数组首元素 arr[0],此时取strlen无法 '\0' 来结尾 ,所以为非法行为。

printf ("%d\n", strlen(arr[1]));   //未定义行为

    ④  理由 同上, arr[1],此时取strlen无法 '\0' 来结尾 ,所以为非法行为。

printf ("%d\n", strlen(&arr));   //6

    ⑤ &arr为数组指针,指向数组的起始位置,取strlen 从此处开始往后找 '\0'的位置,取到长度为 6

printf ("%d\n", strlen(&arr + 1));   //未定义行为

    ⑥ 数组指针 + 1,表示跳过整个数组,即为指向 '\0' 后面位置的数组指针,再取strlen ,无法找到 '\0', 为非法行为。

printf ("%d\n", strlen(&arr[0] + 1));   //5

    ⑦ &arr[0]指向数组首元素的地址,&arr[0] + 1 指向数组第二个元素的地址。再取 strlen ,往后找到 '\0' 的地址,长度为5 。

 

4. char* 型数组名指向字符串,char*数组名与指针转换,求 sizeof 和 strlen

char* p = "abcdef";    //定义字符型指针变量p指向字符串

 以下严格按照一行代码,再加一行解释的格式来书写

求sizeof

printf ("%d\n", sizeof(p));    //4

    ① p 为指针变量,sizeof(p) 长度即为 4 。

printf ("%d\n", sizeof(p + 1));    //4

    ② p + 1,指针加 1 还是指针,sizeof(p + 1)长度也为 4 。

printf ("%d\n", sizeof(*p));    //1

    ③ *p 解引用取到数组首元素 'a' ,长度为 1 。

printf ("%d\n", sizeof(p[0]));    //1

    ④ 由 p[0] == *p两个写法所指向内容相同, 'a' 长度为 1 。

printf ("%d\n", sizeof(&p));    //4

     ⑤ p 为指针类型变量,再取地址 &p  为二级指针,所以指针长度为 4 。

printf ("%d\n", sizeof(&p + 1));    //4

    ⑥ &p + 1,二级指针加 1 ,还是指针,长度为 4 。

printf ("%d\n", sizeof(&p[0] + 1));    //4

    ⑦ p[0] == *p ,解引用再取地址(&p[0]), 为char*,char* + 1长度还为 4 。

求strlen

printf ("%d\n", strlen(p));    //6    

    ① p 为指针变量,指向数组首元素的地址,取strlen 从此处往后找 '\0' 的地址,即长度为 6 。

printf ("%d\n", strlen(p + 1));    //5  

    ② p指向首元素地址,p + 1指向第二个元素地址,再取strlen 从此处往后找 '\0' 的地址,即长度为 5 。

printf ("%d\n", strlen(*p));    //未定义行为

    ③ *p == p[0] 取到 'a' ,无法找到 '\0' ,为非法操作 。

printf ("%d\n", strlen(p[0]));    //未定义行为

    ④ p[0] == *p 取到 'a' ,无法找到 '\0' ,为非法操作 。

printf ("%d\n", strlen(&p));    //未定义行为  

    ⑤ p 为指针类型变量,再取地址 &p  为二级指针,对类型求 strlen 为非法行为

printf ("%d\n", strlen(&p + 1));    //未定义行为  

    ⑥ &p + 1,二级指针加 1 ,还是指针,对类型求 strlen 为非法行为

printf ("%d\n", strlen(&p[0] + 1));    //5  

    ⑦  p[0] == *p ,解引用再取地址(&p[0]),此时为指向 'a' 的指针,(&p[0] + 1)为指向 'b' 的指针。再取strlen 从此处开始找到 '\0' 的地址,长度为 5 。

 

5. 二位整型数组,数组名与指针转换,求 sizeof 和 strlen

 int a[3][4] = {0};     //表示长度为3的一维数组,每个元素是长度为4的一维数组

以下严格按照一行代码,再加一行解释的格式来书写

求sizeof

printf ("%d\n", sizeof(a));    //48

    ① 二维数组名取sizeof,共12个int型元素,长度为48 。

printf ("%d\n", sizeof(a[0][0]));    //4

    ② a[0][0] 取第一行第一列的元素,为一个int,长度为4 。

printf ("%d\n", sizeof(a[0]));    //16

    ③ 取第一行所以元素,第一行有4和元素,为4个int,长度为 16 。

printf ("%d\n", sizeof(a[0] + 1));    //4

    ④ 数组名 + 1,转换为指针。指针类型长度为 4 。

printf ("%d\n", sizeof(*(a[0] + 1)));    //4

    ⑤ 等式转换 : *(p + 1)  =>  p[1]

                             *(a[0] + 1)  =>  a[0][1]  ,指向第一行第二列的元素,一个int,长度为 4 。

printf ("%d\n", sizeof(a + 1));    //4

    ⑥ 数组名 + 1,转换为 指针,长度为 4 。

printf ("%d\n", sizeof(*(a + 1)));    //16

    ⑦ *(a  + 1)  => a[1], 代表二维数组第二行的四个元素,四个int长度为 16 。

printf ("%d\n", sizeof(&a[0] + 1));    //4

    ⑧ &a[0] 数组名取地址,转换为数组指针,指针 + 1还是指针,长度为4 。

printf ("%d\n", sizeof(*(&a[0] + 1)));    //4

    ⑨ *(&a[0] + 1)  =>  (&a[0])[1],为取(&a[0])四个元素数组指针的第二个元素,即长度为4 。

printf ("%d\n", sizeof(*a));    //16

    ⑩ *a 取二维数组的首元素 a[0],为4个int,长度为16 。

printf ("%d\n", sizeof(a[3]));    //16

       上式 a[3],此处3为越界行为(3个元素取得时候只能是0 1 2),但此时为编译求值并不影响程序运行。

 

总结

 1.数组名的意义

       ① sizeof(数组名),此处数组名表示对整个数组求大小

       ② &数组名, 取的是整个数组的地址

       ③ 除上面两种情况,其他所有的数组名都表示首元素的地址。

 2.数组名和指针间的转换

       ① 数组名 加减 数字时,转换为指针。

       ② 数组名作为函数参数使用时,隐式转换为指向数组首元素的指针。

       ③ 数组名取地址,转换为指向整个数组首元素的数组指针。

 3.几种等式相互转换

       ①  对于指针变量指向的字符数组: *数组名  ==  数组名[0]。  //*p = p[0]

       ② 一维数组:*(数组名 + 1)   ==  数组名 [1]。 //*(p + 1)  ==  p[1]

       ③ 二维数组:*(数组名[0] + 1)  ==  数组名[0][1] 。// *(a[0] + 1) == a[0][1]

       ④ 二维数组:*(&数组名[0] + 1)  ==  (&数组名[0]) [1]。//*(&a[0] + 1) == (&a[0])[1]

4.指针数组与数组指针

    指针数组

int* arr [10];

     指针数组是一个数组,数组的每个元素都是一个指针。

 

  数组指针

int (*arr)[10];

    数组指针是  指针,这个指针指向十个元素的数组。

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值