(C语言)指针:让世俗沉沦我的美

       

目录

       

前言

一、训前热身    

二、知识储备

三、训练开始

        (1),一维数组笔试题分析

 (2)字符数组

       1.0

 2.0

3.0

 (3)二维数组笔试题分析


前言

                在学习c语言过程中,指针就像是妖魔鬼怪,形式多变,时不时隐身,出入在代码的各个角落,让我们为之抓狂。

为了深入了解和理解指针的内容,我们将会详细探讨一维数组,二维数组,数组指针,指针数组和指针有什么关系以及他们之间的互化关系。

一、训前热身    

        下面给出几组训练,试试是否可以正确写出输出的值

int a [] = { 1 , 2 , 3 , 4 };
printf ( "%d\n" , sizeof ( a ));
输出 4;
char arr [] = { 'a' , 'b' , 'c' , 'd' , 'e' , 'f' };
printf ( "%d\n" , sizeof ( arr ));
输出 6;
char arr [] = "abcdef" ;
printf ( "%d\n" , sizeof ( arr ));
输出 7;
char * p = "abcdef" ;
printf ( "%d\n" , sizeof ( p ));

输出 1;

int a [ 3 ][ 4 ] = { 0 };
printf ( "%d\n" , sizeof ( a ));
输出 48;

         看到这里,想必对于初学者或多或少会有些许疑问,这个为什么输出的答案是这个?那个怎么又变了?或者完全不懂为什么输出这个数字。接下来我会和大家深究答案为何而来

二、知识储备

        sizeof()函数 :此函数计算的是某个类型的字节大小或空间大小,比如sizeof(int)=4(字节)

        strlen()函数:此函数计算的是数组元素长度,比如strlen(“abcdef”)=6(字节)strlen计算长度时,遇到‘\0’停止计算;

        ①sizeof(数组名):这里的数组名表示整个数组,计算的是整个数组的大小;

        ②&数组名:这里的数组名表示整个数组,取出的是整个数组的地址;

        除上述两种情况之外,所有的数组名都表示数组首元素的地址;

三、训练开始

        (1),一维数组笔试题分析

        ①sizeof(数组名):这里的数组名表示整个数组,计算的是整个数组的大小;

        ②&数组名:这里的数组名表示整个数组,取出的是整个数组的地址;

        除上述两种情况之外,所有的数组名都表示数组首元素的地址;

int main()
{
    int a[] = { 1,2,3,4 };

//1
    printf("%d\n", sizeof(a));//解释:a是一个数组名 根据 1. 数组名a代表整个数组,计算的是整个数组的大小 答案 :4*4=16

//2
    printf("%d\n", sizeof(a + 0));//解释:a+0不满足 1. 中的条件(仅有数组名a在括号内)这此a为数组首元素地址 

                                                //而且a+0带标跳过0个元素 即为首元素地址,指针(地址)的大小为4或8 答案:4 or 8;

//3
    printf("%d\n", sizeof(*a));//解释:*a不满足 1. 的条件 数组名a为首元素地址 然后解引用得到的是整型元素 1 大小为 4

                                                //答案 :4

//4
    printf("%d\n", sizeof(a + 1));//解释:同第二题  计算的是a+1处地址的大小 为 4 or 8 答案:4or8

//5
    printf("%d\n", sizeof(a[1]));//解释 a[1] 取出的是整型数组中的一个元素 大小为4 答案:4

//6
    printf("%d\n", sizeof(&a));//解释:&a 由 2. 知 代表整个数组的地址 求地址的大小即指针大小 为4or8 答案:4or8

//7
    printf("%d\n", sizeof(*&a));//解释:*&a=a  当*在&的前时 即*&可直接相抵消 由题一知 为16 答案 16

//8
    printf("%d\n", sizeof(&a + 1));//解释:&a+1 代表的还是一个地址 大小仍然为 4 or 8 答案:4or8

//9
    printf("%d\n", sizeof(&a[0]));//解释:取的是a[0]的地址 大小为 4 or 8 答案4or8

//10
    printf("%d\n", sizeof(&a[0] + 1));//解释:地址+1 还是地址 大小为 4 or 8 答案 4 or 8


    return 0;

}

1. 16

2.  4or8

3.  4

4. 4or8

5. 4

6. 4or8

7. 16

8. 4or8

9. 4or8

10. 4or8

#include<stdio.h>
int main()
{
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a + 0));
	printf("%d\n", sizeof(*a));
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(a[1]));
	printf("%d\n", sizeof(&a));
	printf("%d\n", sizeof(*&a));
	printf("%d\n", sizeof(&a + 1));
	printf("%d\n", sizeof(&a[0]));
	printf("%d\n", sizeof(&a[0] + 1));
	return 0;
}

 代码运行结果:左:x86运行系统下         右:x64运行系统下

 (2)字符数组

       1.0

        ①sizeof(数组名):这里的数组名表示整个数组,计算的是整个数组的大小;

        ②&数组名:这里的数组名表示整个数组,取出的是整个数组的地址;

        除上述两种情况之外,所有的数组名都表示数组首元素的地址;

#include<stdio.h>
int main()
{
    char arr[] = { 'a','b','c','d','e','f' };//char类型元素为字节大小为 1
    //1.
    printf("%d\n", sizeof(arr));//解释:由 ①知 arr 单列在sizeof中表示整个数组 求的是整个数组的大小 为1*6=6;
    //2.
    printf("%d\n", sizeof(arr + 0));//解释:不符合①的条件,表示求首元素地址大小 为 4 or 8;
    //3.
    printf("%d\n", sizeof(*arr));//解释:不符合①的条件,*arr表示求首元素的大小 为1
    //4.
    printf("%d\n", sizeof(arr[1]));//解释:求数组第二个元素的大小 为 1;
    //5.
    printf("%d\n", sizeof(&arr));//解释:&arr 表示取整个数组的地址 求地址大小 为 4or8;
    //6.
    printf("%d\n", sizeof(&arr + 1));//解释:&arr+1表示数组地址后面+1的地址 求地址大小 为4or8;
    //7.
    printf("%d\n", sizeof(&arr[0] + 1));//解释:&arr[0] + 1表示数组首元素后面一个元素的地址 求地址大小 为4or8;
    //8.
    printf("%d\n", strlen(arr));//解释:strlen(arr)求字符串长度遇到'\0'停止,此数组中无‘\0'将会遇到’\0‘停止 为随机值;
    //9.
    printf("%d\n", strlen(arr + 0));//解释:同8. 为随机值
    //10
    //printf("%d\n", strlen(*arr));//解释:*arr 表示首元素a 我们传进去必须是一个地址 为err
    //11.
    //printf("%d\n", strlen(arr[1]));//解释:同 10.
    printf("err\n");
    printf("err\n");//运行结果会报错 屏蔽掉打印err
    //12.
    printf("%d\n", strlen(&arr));//解释:&arr表示整个数组的地址,从第一个元素的地址开始计算长度无结束符 为随机值;
    //13.
    printf("%d\n", strlen(&arr + 1));//解释:&arr+1表示整个数组后面的一个元素的地址开始计算,无结束符 为 随机值-6
    //14.
    printf("%d\n", strlen(&arr[0] + 1));//解释:&arr[0] + 1表示从数组的第二个元素的地址开始计算 无结束符 为 随机值-1
}

    1. 6
    2. 4or8
    3. 1
    4. 1
    5. 4or8
    6. 4or8
    7. 4or8
    8. 随机值
    9.随机值
    10.err
    11.err
    12.随机值
    13.随机值-6
    14.随机值-1

 

 

#include<stdio.h>
int main()
{
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a + 0));
	printf("%d\n", sizeof(*a));
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(a[1]));
	printf("%d\n", sizeof(&a));
	printf("%d\n", sizeof(*&a));
	printf("%d\n", sizeof(&a + 1));
	printf("%d\n", sizeof(&a[0]));
	printf("%d\n", sizeof(&a[0] + 1));
	return 0;
}

代码运行结果如下:

 

 2.0

        ①sizeof(数组名):这里的数组名表示整个数组,计算的是整个数组的大小;

        ②&数组名:这里的数组名表示整个数组,取出的是整个数组的地址;

        除上述两种情况之外,所有的数组名都表示数组首元素的地址;

#include<stdio.h>
int main()
{

    char arr[] = "abcdef";//此数组中最后一个元素是’\0‘
    //1.
    printf("%d\n", sizeof(arr));//解释:由①知,计算的是整个数组的大小 为 7
    //2.
    printf("%d\n", sizeof(arr + 0));//解释:不满足① arr+0表示首元素的地址 求地址大小为 4or8
    //3.
    printf("%d\n", sizeof(*arr));//解释:*arr表示首元素 求元素字节为 1
    //4.
    printf("%d\n", sizeof(arr[1]));//解释:arr[1]表示数组第二个元素 求元素字节为 1
    //5.
    printf("%d\n", sizeof(&arr));//解释:&arr表示取整个数组的地址 求地址大小为 4or8
    //6.
    printf("%d\n", sizeof(&arr + 1));//解释:&arr + 1表示数组后的第一个元素的地址,求地址大小为 4or8
    //7.
    printf("%d\n", sizeof(&arr[0] + 1));//解释:求地址大小为 4or8

    //8.
    printf("%d\n", strlen(arr));//解释:从首元素开始到’\0‘结束为 6
    //9.
    printf("%d\n", strlen(arr + 0));//解释:同8. 为6
    10.
    //printf("%d\n", strlen(*arr));//解释:err
    11.
    //printf("%d\n", strlen(arr[1]));//解释:err
    printf("err\n");
    printf("err\n");
    //12.
    printf("%d\n", strlen(&arr));//解释:从数组首元素地址开始计算到’\0‘结束为6
    //13.
    printf("%d\n", strlen(&arr + 1));//解释:从数组后的一个元素地址开始计算到’\0‘结束 为随机值
    //14.
    printf("%d\n", strlen(&arr[0] + 1));//解释:从数组第二个元素地址开始计算到’\0‘结束为5
}

1. 7
2. 4or8
3. 1
4. 1
5. 4or8
6. 4or8
7. 4or8
8. 6
9. 6
10.err
11.err
12.6
13.随机值
14.5

 

#include<stdio.h>
int main()
{

	char arr[] = "abcdef";
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr + 0));
	printf("%d\n", sizeof(*arr));
	printf("%d\n", sizeof(arr[1]));
	printf("%d\n", sizeof(&arr));
	printf("%d\n", sizeof(&arr + 1));
	printf("%d\n", sizeof(&arr[0] + 1));
	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));
}

代码运行结果如下: 

 

3.0

        ①sizeof(数组名):这里的数组名表示整个数组,计算的是整个数组的大小;

        ②&数组名:这里的数组名表示整个数组,取出的是整个数组的地址;

        除上述两种情况之外,所有的数组名都表示数组首元素的地址;

#include<stdio.h>
int main()
{
    char* p = "abcdef";//p是一个char*型的指针变量指向的的是常量字符串"abcdef"的首地址 即字符a的地址
    //强调 p是一个指针(地址)
    //1.
    printf("%d\n", sizeof(p));//解释:求地址p的大小为 4 or 8
    //2.
    printf("%d\n", sizeof(p + 1));//解释:求地址p+1的大小为 4 or 8
    //3.
    printf("%d\n", sizeof(*p));//解释:*p 表示取首地址的内容即字符a 求字符元素的大小为 1
    //4.
    printf("%d\n", sizeof(p[0]));//解释:p[0]=*(p+0) 即求字符a的大小为1
    //5.
    printf("%d\n", sizeof(&p));//解释:&p 表示是取指针p的地址 还是求地址的大小为 4or8
    //6.
    printf("%d\n", sizeof(&p + 1));//解释:求地址大小 为 4or8
    //7.
    printf("%d\n", sizeof(&p[0] + 1));//解释:求地址大小为 4or8

    //8.
    printf("%d\n", strlen(p));//解释:p为数组首地址 从此处计算长度 到结束符结束 为6
    //9.
    printf("%d\n", strlen(p + 1));//解释:p+1为数组第二个元素地址 从此处计算长度 到结束符结束 为5
    //printf("%d\n", strlen(*p));//解释:*p 解引用得到字符串"abcdef" 未知地址 err
    //printf("%d\n", strlen(p[0]));//解释:同上
    //10.
    printf("err\n");
    //11.
    printf("err\n");
    //12.
    printf("%d\n", strlen(&p));//解释:&p 把指针变量p 存放在一个地址上 从此地址开始计算 到结束符结束 为随机值
    //13.
    printf("%d\n", strlen(&p + 1));//解释:&p 把指针变量p 存放在一个地址上 从此地址+1处开始计算 到结束符结束 为随机值
    //14.
    printf("%d\n", strlen(&p[0] + 1));//解释:p[0]=*(p+0) &p[0]即为一个元素a的地址然后跳过一个元素的地址 计算到结束符 为5
}

1. 4 or 8
2. 4 or 8
3. 1
4. 1
5. 4or8
6. 4or8
7. 4or8
8. 6
9. 5
10.err
11.err
12.随机值
13.随机值
14.5

#include<stdio.h>
int main()
{
	char* p = "abcdef";
	printf("%d\n", sizeof(p));
	printf("%d\n", sizeof(p + 1));
	printf("%d\n", sizeof(*p));
	printf("%d\n", sizeof(p[0]));
	printf("%d\n", sizeof(&p));
	printf("%d\n", sizeof(&p + 1));
	printf("%d\n", sizeof(&p[0] + 1));

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

 代码运行结果如下:

 (3)二维数组笔试题分析

        

         ①sizeof(数组名):这里的数组名表示整个数组,计算的是整个数组的大小;

        ②&数组名:这里的数组名表示整个数组,取出的是整个数组的地址;

        除上述两种情况之外,所有的数组名都表示数组首元素的地址;

#include<stdio.h>
int main()
{
    int a[3][4] = { 0 };//a[3][4]二维数组 可看做有三个元素的一维数组,每个元素又是有四个元素一维数组
    //1.
    printf("%d\n", sizeof(a));//解释:数组名a表示 整个数组符合① 求数组总元素大小为 4*3*4=48
    //2.
    printf("%d\n", sizeof(a[0][0]));//解释:a[0][0] 表示求第一行第一列的元素的大小为 4
    //3.
    printf("%d\n", sizeof(a[0]));//解释:a[0]表示一个一维数组名, 符合①, 这个数组元素代表第一行,元素有四个 大小为 16
    //4.
    printf("%d\n", sizeof(a[0] + 1));//解释:a[0]表示第一行元素的地址在加一 那么这里表示地址 求地址大小为 4 or 8 
    //5.
    printf("%d\n", sizeof(*(a[0] + 1)));//解释:a[0] + 1表示第一行首元素的地址加一 表示第一行第二列的地址,然后解引用 就是求元素的大小为4
    //                                a[i]=*(a+i)----*(a[i] + j))=*(*(a+i) + j))=a[i][j]
    //6.
    printf("%d\n", sizeof(a + 1));//解释:a+1表示第一行第二列元素的地址 求地址大小为4or8
    //7.
    printf("%d\n", sizeof(*(a + 1)));//解释:*(a+1)=a[1] 表示一个一维数组 求该一维数组大小 大小为16
    //8.
    printf("%d\n", sizeof(&a[0] + 1));//解释:取把第一行地址的地址 然后+1 求地址大小为4or8
    //9.
    printf("%d\n", sizeof(*(&a[0] + 1)));//解释:&a[0] + 1说明是第二行地址的地址 然后解引用表示第二行求得大小为:4*4=16
    //10.
    printf("%d\n", sizeof(*a));//解释:*a=a[0]代表二维数组的首行  求得 大小为4*4=16
    return 0;
}

1. 48
2. 4
3. 16
4. 4 or 8 
5. 4
6. 4or8
7. 16
8. 4 or 8 
9. 16
10.16

#include<stdio.h>
int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a[0][0]));
	printf("%d\n", sizeof(a[0]));
	printf("%d\n", sizeof(a[0] + 1));
	printf("%d\n", sizeof(*(a[0] + 1)));
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(*(a + 1)));
	printf("%d\n", sizeof(&a[0] + 1));
	printf("%d\n", sizeof(*(&a[0] + 1)));
	printf("%d\n", sizeof(*a));
	return 0;
}

 代码运行结如下:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值