精华内容
下载资源
问答
  • 什么是C语言数组地址

    千次阅读 2019-06-19 22:29:01
    还记得以前有和同事聊过C语言数组这个概念,那时候大家都还不是掌握的很好,总会搞错数组的地址。但是总有人会对数组的地址这个概念产生怨念,他们认为一个数组a本身就是地址,殊不知数组名a只是其元素的地址,而&...

    还记得以前有和同事聊过C语言数组这个概念,那时候大家都还不是掌握的很好,总会搞错数组的地址。但是总有人会对数组的地址这个概念产生怨念,他们认为一个数组a本身就是地址,殊不知数组名a只是其首元素的地址,而&a才是数组a的地址。

    拓展:

    假设有一个数据 int a[5];

    那么,a代表的是a[0]的地址,换句话说,a等价于&a[0],假如这个地址值是0x123,那么a+1的值是0x127,因为这个1代表的是1个int(4个字节)型数据。

    另外,&a代表的是整个数组的地址,这个地址值也是0x123,但是&a+1的值是0x143,因为这个1代表的是1个int [5](20个字节)数组。

    通过上面的描述,是不是一下子清晰明了了,可以动手实践下。

     

    本文地址:http://www.soo1.top/?id=53

    展开全文
  • C语言数组首地址和数组第一个元素的地址关系如下: 1、它们的地址值相等的。 2、第1个元素的地址如果p,则p+1就是第2个元素的地址。 3、数组的首地址如果p,则p+1就跳过这个数组而指向这个数组最后一个...

    C语言中数组首地址和数组第一个元素的地址关系如下:

    1、它们的地址值是相等的。

    2、第1个元素的地址如果是p,则p+1就是第2个元素的地址。

    3、数组的首地址如果是p,则p+1就跳过这个数组而指向这个数组最后一个元素最后一个字节的下一字节。

    参考:https://zhidao.baidu.com/question/581103677.html

    展开全文
  • 深入理解c语言数组

    2021-01-21 18:29:19
    有的资料说:数组名指向数组首地址的常量指针。 下面我们可以验证一下。我都知道sizeof操作符可以返回一个对象或者类型所占的内存字节数。如:int i=1;那么sizeof(i) 的结果就是4(64位机器下的部分编译器8) 那...
  • C语言数组

    2020-06-29 20:34:17
    今天学习了数组 总结和分享一下自己觉得重要的一些点。 一、什么是数组? 1.数组是数据的集合。 2.数组的数据同类型的 不能又有整数 又有小数等。...函数传参数过去其实只是数组首地址。而不是整个数组。 ...

    数组

    数组是什么?

    1.数组是数据的集合
    2.数组的数据是同类型的 不能是又有整数 又有小数等。
    3.数组地址连续的。

    为什么要用?

    需要大量数据同时也不关心名称的时候,比较方便。
    对于数据个数比较多的时候,像我们想定义100个整型变量存放数据,你是不是我们直接定义 int a,b,c,d,e…到100个就好啦? 这显然是极其麻烦的并且傻瓜的一种做法。所以我们需要用到数组。

    一维数组

    如何定义?

    类型 + 名字 + 多少个(多大)
    例子:

    创建一个能装100个数据的整型变量

    整型 名字 个数
    int array[100]; 
    

    创建一个能装100个数据的浮点型变量

    浮点型 名字 个数
    float array[100];
    

    如何初始化?

    整型:

    //定义了一个整型数组 个数5个 分别为1 2 3 4 5
    int array[5] = {1,2,3,4,5}; 
    //定义了一个整型数组 个数5个 部分初始化 分别为1 2 后面的默认没写是为 0 的
    int array[5] = {1,2};
    

    错误写法(越界):

    int array{5} = {1,2,3,4,5,6,7,8}; //超出范围了 越界了 定义了5个 存放了8个
    

    其他类型也一样。

    浮点型:

    //定义了一个浮点型数组 个数5个 分别为1.1 2.2 3.3 4.4 5.5
    float array[5] = {1.1,2.2,3.3,4.4,5.5};
    //定义了一个浮点型数组 个数5个 部分初始化 分别为1.1  后面的默认  为0.0
    float array[5] = {1.1};
    

    有时候你定义一个数组都得数一数元素个数,其实可以不用写多少个。
    也可以这样定义:

    
    int array[] = {1,2,3,4,5};
    

    如何引用?

    int a[3] = {1,2,3};
    其实就是 a[0] = 1; a[1] = 2; a[3] = 2; 下标是从0开始算的
    我们可以通过下标的方式访问。

    打印单个数组数据
    比如我想打印第数组的第5个数据array[4]

    printf("%d\n",array[4]);
    printf("%d\n",array[2*2]);
    

    打印整个数组数据
    首先打印得知道数组数据个数。你可能会说定义的时候不就写上了吗?
    那我想说 int array[] = {1,2,3,4,5}; 这样呢?难道又去数数?
    我们可以通过数组的大小来确定数组数据个数
    int 类型是4字节。如果数组大小为8字节 那是不是就是数组个数为2。
    像下面这样,比较推荐第一种来写。

    length = sizeof(array)/sizeof(array[0]);
    length = sizeof(array)/sizeof(int);
    length = sizeof(array)/sizeof(4);
    

    通过for循环来:

    int array[5] = {1,2,3,4,5};
    int array1[] = {1,2,3,4,5};
    
    /*知道数组个数*/
    for(i=0;i<5;i++)
    {
    	printf("%d ",array[i]);
    }
    /*=============================================*/
    length = sizeof(array1)/sizeof(array1[0]);
    /*不知道数组个数*/
    for(i=0;i<length;i++)
    {
    	printf("%d ",array1[i]);
    }
    
    输出结果:1,2,3,4,5	(两个都是)
    

    一维数组在内存中的存储

    我们通过代码打印一下每个数据的地址吧

    int array[] = {5,4,3,2,1};
    int length; //计算数组个数
    int i;
    length = sizeof(array)/array[0];
    for(i=0;i<length;i++)
    {
    	printf("array[%d]地址:%p\n",i,&array[i]);
    }
    
    输出结果:
    array[0]地址:0060FED4
    array[1]地址:0060FED8
    array[2]地址:0060FEDC
    array[3]地址:0060FEE0
    

    发现了地址是从低往高存放的,地址是连续的 一个占4字节。

    一维数组运用举例

    一、找最大值
    #include <stdio.h>
    #include <stdlib.h>
    int main()
    {
    	int i = 0;//遍历数组
        int array[5]; //存放数据
        int max = 0; //存放最大值
        while(i != 5)
        {
    		printf("请输入第 %d 个数\n",i+1);
    		scanf("%d",&array[i]);
            i++;
        }
        
        printf("数据: ");    
    	for(i=0;i<5;i++)
    	{
    		printf("%d ",array[i]);
    	}
    	printf("\n");	
        max = array[0]; //把第一项给max 
        /*找最大值*/
        for(i=1;i<5;i++)
        {
    		if(array[i] > max)
            {
    			max = array[i];
            }
    			
    	}
    	printf("最大值为%d\n",max);
        system("pause");
    	return 0;
    }
    
    

    运行结果:
    在这里插入图片描述

    二、冒泡法排序(从小到大)

    就是每次将相邻的两个数对比,把小的放到前面,如果有5个数:5 4 3 2 1。首先先5跟4对比 4最小 4放到前面 变成 4 5 3 2 1。然后继续5跟3对比,3最小,3放在前面。变成 4 3 5 2 1…直接看图吧。
    在这里插入图片描述
    我们会发现一个规律,总共进行了4轮(数组个数-1),每一轮都在减一。
    那么通过for循环嵌套,如果i 代表是大的循环(4轮)j 表示里面互换次数的循环。

    大循环好办 就是数组个数-1。 你5个 就for循环就是 4。

    for(i=0;i<length-1;i++)
    {
    	
    }
    

    那么内循环 j 我们看图发现 第一轮进行了4次对比,正好是数组个数-1。第二轮进行了3次,第三轮进行了2次,第四轮进行了1次。
    就是要j 第一次循环4次 第二次 循环3次 第三次 循环2次 第四次 1次。
    刚好就是数组个数-i 就是大循环的次数-i

    for(j=0;j<(length-1)-i;j++)
    {
    	我们得知数组个数为5 	5-1=4.
    /*	第一轮i=0;	当j=0;		4-i = 4 	可以进行4次循环
    	第二轮i=1;	当j=1; 		4-i = 3		可以进行3次循环
    	第三轮i=2;	当j=2;		4-i = 2		可以进行2次循环	
    	第四轮i=3;	当j=3;		4-i = 1		可以进行1次循环	 	*/
    }
    

    完整程序:

    #include <stdio.h>
    
    int main()
    {
        int array[] = {5,4,3,2,1};
        int length; //计算数组个数
        int i,j;
        int max; 
    	length = sizeof(array)/sizeof(array[0]); //计算出数组个数
        
    	/*开始排序*/
        for(i=0;i<length-1;i++)
        {
    		for(j=0; j<(length-1)-i;  j++)
            {
    			if(array[j] > array[j+1]) //判断哪个大
                {
    				max = array[j]; //大的给max
                    array[j] = array[j+1]; //把小的放在前面。
                    array[j+1] = max; //大的值放回后面
                }
            }
        }
        
        /*排序结果输出*/
        printf("从小到大:");
        for(i=0;i<length;i++)
        {
    		printf("%d ",array[i]);
    	}
        system("pause");
    	return 0;
    }
    
    输出结果:1 2 3 4 5
    

    二维数组

    如何定义?

    二维数组就相当于一个矩阵,有行有列。比如下面定义的就是两行三列。

    int array[2][3];
    

    如何初始化?

    类型 + 名字 + [行]][列];
    注意:二维数组变量定义的时候 必须要有列的大小 可以没有行
    正确的定义并初始化:

    int array1[2][3] = {{1,2,3},{4,5,6}};
    int array2[2][3] = {1,2,3,4,5,6};
    int array3[][3] = {{1,2,3},{4,5,6}};
    int array4[][3] = {1,2,3,4,5,6};
    

    错误定义

    int array[][] = {{1,2,3},{4,5,6}}; //至少也要有列
    int array[2][] = {{1,2,3},{4,5,6}}; //没有列
    int array[2][3] {{1,2,3},{4,5,6},{7,8,9}};//越界 超出范围
    

    如何引用?

    比如:

    int array[2][3] = {{1,2,3},{4,5,6}};
    
    排列顺序:
    array[0][0] —→ array[0][1] —→ array[0][2] 
    array[1][0] —→ array[1][1] —→ array[1][2] 
    

    下标是从0开始算的

    打印单个数据
    比如我想打印第一行,第二个数据 即 2 array[0][1];

    printf("%d\n",array[0][1]);
    printf("%d\n",array[0*0][1*1]); //显得有点多余。。。
    

    打印整个数组数据
    首先得知道行数 和 列数:

    sizeof(array[0][0]);	为一个元素占用的空间,
    sizeof(array[0]);	为一行元素占用的空间,
    sizeof(array);	为整个数组占用的空间,
    
    行:line = sizeof(array)/sizeof(array[0]);
    列:column = sizeof(array[0]/sizeof(array[0][0]))
    

    通过for循环打印全部数组

    
    int i,j;
    int array[2][3] = {{1,2,3},{4,5,6}};
    int size,line,column;
    size = sizeof(array);//获取大小
    line = sizeof(array)/sizeof(array[0]); //行
    column = sizeof(array[0])/sizeof(array[0][0]); //列
    printf("size:%d\n",size);
    printf("line:%d\n",line);
    printf("column:%d\n",column);
    
    for(i=0;i<line;i++)
    {
    	for(j=0;j<column;j++)
        {
    		printf("array[%d][%d]:%d \n",i,j,array[i][j]);
        }
    }
    
    输出结果:
    
    size:24
    line:2
    column:3
    array[0][0]:1
    array[0][1]:2
    array[0][2]:3
    array[1][0]:4
    array[1][1]:5
    array[1][2]:6
    

    二维数组在内存中的存储

    二维数组是按行存放的,在内存中先放第一行的 然后 第二…

    通过编程来查看地址:

    #include <stdio.h>
    
    int main()
    {
    	int i,j;
    	int array[2][3] = {{1,2,3},{4,5,6}};
        int size,line,column;
        size = sizeof(array);//获取大小
        line = sizeof(array)/sizeof(array[0]); //行
        column = sizeof(array[0])/sizeof(array[0][0]); //列
        printf("size:%d\n",size);
        printf("line:%d\n",line);
        printf("column:%d\n",column);
        for(i=0;i<line;i++)
        {
    		for(j=0;j<column;j++)
            {
    			printf("array[%d][%d]地址:%p \n",i,j,&array[i][j]);
            }
        }
        system("pause");
    	return 0;
    }
    
    输出结果:
    size:24
    line:2
    column:3
    array[0][0]地址:0060FEC4
    array[0][1]地址:0060FEC8
    array[0][2]地址:0060FECC
    array[1][0]地址:0060FED0
    array[1][1]地址:0060FED4
    array[1][2]地址:0060FED8
    

    跟一维数组一样。

    二维数组运用举例

    一、推箱子地图绘制
    #include <stdio.h>
    
    int main()
    {
    	int i,j;
    	int Map[8][8] = {
        0,0,1,1,1,0,0,0,
        0,0,1,2,1,0,0,0,
        0,0,1,0,1,1,1,1,
        1,1,1,3,0,3,2,1,
        1,2,0,3,4,1,1,1,
        1,1,1,1,3,1,0,0,
        0,0,0,1,2,1,0,0,
        0,0,0,1,1,1,0,0,
        };
        /*地图显示*/
        for(i=0;i<8;i++)
        { 
    		for(j=0;j<8;j++)
    		{	
    			switch(Map[i][j])
    			{	
    				case 0: printf("  "); break;         
    				case 1: printf("▇"); break;//围墙
    				case 2: printf("★"); break; //目的地
    				case 3: printf("●"); break; //箱子
    				case 4: printf("♂"); break;//人      
    			}
    				if((j+1)/8==1) //够8次 换行
                    {                
    					putchar('\n');
                    }
            }	
        }
    	return 0;
    }
    
    

    输出结果:
    在这里插入图片描述
    如果有的运行结果不像图中这样 把符号变成其他。改成*啥的

    二、实现二维数组行列互换。
    #include <stdio.h>
    
    int main()
    {
    	int array[2][3] = {{1,2,3},{4,5,6}};
        int newArray[3][2];
        int i,j;
        /*原有数组输出数据*/
    	for(i=0;i<2;i++)
    	{
    		for(j=0;j<3;j++)
            {
    			printf("array[%d][%d]: %d ",i,j,array[i][j]);
            }
            printf("\n");
        }
        /*变换行列*/
        for(i=0;i<2;i++)
        {
    		for(j=0;j<3;j++)
            {
    			newArray[j][i] = array[i][j];
            }
        }  
        /*新数组输出数据*/
        printf("\n=======变换行列结果========\n\n");
        for(i=0;i<3;i++)
    	{
    		for(j=0;j<2;j++)
            {
    			printf("newArray[%d][%d]: %d ",i,j,newArray[i][j]);
            }
            printf("\n");
        }
    
    	return 0;
    }
    
    
    输出结果:
    array[0][0]: 1 array[0][1]: 2 array[0][2]: 3
    array[1][0]: 4 array[1][1]: 5 array[1][2]: 6
    
    =======变换行列结果========
    
    newArray[0][0]: 1 newArray[0][1]: 4
    newArray[1][0]: 2 newArray[1][1]: 5
    newArray[2][0]: 3 newArray[2][1]: 6
    

    字符数组

    如何定义?

    字符很显然我是用char类型对吧。
    定义一个char类型数组 数组个数是10个。

    char string[10];
    

    如何初始化?

    定义一个字符数组 存放HelloWorld。

    char string1[10] = {'H','e','l','l','o','W','o','r','l','d'}; //这种比较麻烦
    char string2[10] = "HelloWorld"; //这种是比较简单 没那么麻烦
    char string3[] = "HelloWorld"; //这种更简单 省略数组个数
    

    如何引用?

    1.通过访问下标的方式 一个一个字符的输出。——for循环 或者 while()循环

    通过访问下标的方式:————string1字符数组
    int i;
    //		i < string1整体大小 除以 string1首元素大小
    for(i=0;i<sizeof(string1)/sizeof(string1[0]);i++)
    {
    	printf("%c",string1[i]);	
    }
    printf("\n"); //结束来个换行
    
    输出结果:HelloWorld
    
    

    2.通过%s输出字符串———string2 string3

    //打印string2 内容:
    printf("string2:%s \n",string2); string2 是指 字符串数组的首地址
    
    //打印string3 内容:
    printf("string3:%s \n",string3); string3 是指 字符串数组的首地址
    
    输出结果:
    
    输出结果:
    string2:HelloWorld@
    string3:HelloWorld
    

    这里会发现 string2这个 打印出来字符串 在最后面有个乱码 这是为啥呢?
    其实 在字符串中 字符串会默认以 ‘\0’ 这个符号 作为结束的标志

    解决办法就是把	string2[10] 改成 string2[11]
    

    我们可以打印一下string3这个大小。就知道其实后面有没有多了个元素。

    printf("string3的大小:%d\n",sizeof(string3));
    
    输出结果:
    11
    

    我们也可以通过检测’\0’ 来输出字符串:

    int i = 0;
    while(string3[i] != '\0')
    {
    	printf("%c",string3[i]);
    	i++;
    }
    
    输出结果:
    HelloWorld
    

    字符数组在内存中的存储

    其实这个可以猜到 char 类型是占一个字节的 那么他们的存储是连续的一次是一个字节。

    字符数组运用举例

    字符串逆序

    就是最前面的元素和最后面的元素互换 第二个元素和倒数第二个元素互换…

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main()
    {
    	char string[] = "ABCDEF";
        int number; //存放插入位置
        int i;
        char str; //存放新字符
        int length;//获取字符串长度
        int moveNumber; //获取移动的次数
        printf("字符串为:%s\n",string);
       
        printf("你想在第几个插入字符?\n");
        scanf("%d",&number);
    	getchar(); //吸收回车键
    
    	printf("插入的字符为:\n");
        scanf("%c",&str);  
    	getchar();
       
        printf("你想在%s 字符串 在第 %d 个插入字符 '%c' \n",string,number,str);
    
        length = strlen(string); //获取字符串的长度
        printf("字符长度:%d\n",length);
        
    	if(length == number)
        {
    		string[length+1] = string[length];//为防止乱码 往右移一位 在Linux上 不需要加这行代码
            string[length] = str; //插入数据
            printf("==============================\n");
    		printf("插入后结果:%s\n",string);
    		printf("==============================\n");
            return 0; //程序结束
        }
        
        
        moveNumber= length-number+1; //获取移动次数
        printf("移动次数:%d\n",moveNumber); 
    	
    	//每一次循环移动一次
    	for(i=0;i<moveNumber;i++) 
        {	
    		string[length-i] = string[length-1-i]; //往右移动
        }
        string[number-1] = str; //插入字符
        printf("==============================\n");
        printf("插入后结果:%s\n",string);
        printf("==============================\n");
    
    	return 0;
    }
    
    
    运行程序结果:
    
    字符串为:ABCDEF
    你想在第几个插入字符?
    2
    插入的字符为:
    G
    你想在ABCDEF 字符串 在第 2 个插入字符 'G'
    字符长度:6
    移动次数:5
    ==============================
    插入后结果:AGBCDEF
    ==============================
    //注:如果最后有乱码 
    //请把string[] = "ABCDEF" 改成 string[8] = "ABCDEF" 或者数组个数更大。
    
    /*
    为什么移动的时候是以下的代码? (都加上了-i)
    string[length-i] = string[length-1-i]; //往右移动
    
    为什么不是下面这个?
    string[length] = string[length-1];
    因为在移动的时候 for循环中 这个是永远都是把最后一个元素往右边移动  
    */
    
    
    去掉字符串左边空格
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
    	char string[] = "  hello"; //左边两个空格  
        int length = strlen(string); //获取字符串的长度
        int i = 0;
        int moveCount = 0; //记录需要移动的次数
        
        printf("长度为:%d\n",length);
    
        
        while(string[i] == ' ' && string[i] != '\0') //检测左边有多少个空格
        {
    		i++;
            moveCount++; //记录次数
        }
        printf("字符串中左边有 %d 个空格.后面的每个元素需要移动次数 %d 次\n",moveCount,moveCount);
    	/*也可以这么计算,增加一个标志位flag*/
    	/*
    	int flag = 1;
    	for(i=0;i<length;i++)
        {
    		if(string[i] == ' ' && string[i] != '\0' && flag == 1)
            {
    			number++;
    		}
            else
            {
    			flag=0; //一旦出现了不是空格 则不再计算左边空格数据
            }
    	}   
    	*/
    
    
        /*循环次数:总共的字符串长度 - 左边的空格数*/
        for(i=0;i<length-moveCount;i++) 
        {
    		string[i] = string[i + moveCount]; //将剩下的元素移动到前面
        }
        
        string[length-moveCount] = '\0'; //紧接着后面加个'\0'
        
        printf("sting:%s\n",string); //输出结果
    
    
    	return 0;
    }
    
    
    输出结果:
    长度为:7
    字符串中左边有 2 个空格.后面的每个元素需要移动次数 2 次
    sting:hello
    
    
    去掉字符串右边空格
    #include <stdio.h>
    #include <stdlib.h>
    int main()
    { 
    	char string[] = "        hello       "; //字符串  
    	int i;
        int number = 0; //计算字符串右边空格数量
        int length = strlen(string); //计算字符串长度
        printf("字符串长度为%d\n",length);
        
        for(i=0;i<length;i++)
        {
    		if(string[i] == ' ' && string[i] != '\0') //计算字符串右边的空格个数
            {
    			number++;
    		}
            else
            {
    			number=0;
            }
    	}
    	printf("右边空格有%d个\n",number);
        
        string[length-number] = '#'; //为了能看出空格 在最后加个#号
        string[length-number+1] = '\0'; 
        printf("string:%s\n",string);
    	return 0;
    }
    
    输出结果:
    字符串长度为20
    右边空格有7个
    string:        hello#
    
    去掉字符串左边的空格和右边的空格

    这个就是比较简单了 把上面的结合一下就行了。

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    { 
    	char string[] = "     he llo       ";   
    	int i;
        int leftNumber = 0;
        int rightNumber = 0;
        int flag = 1; //左边空格标志位
        int length = strlen(string);
        printf("字符串长度为%d\n",length);
        
        /*计算字符串左边的空格数*/
        for(i=0;i<length;i++)
        {
    		if(string[i] == ' ' && string[i] != '\0' && flag == 1)
            {
    			leftNumber++;
    		}
            else
            {
    			flag=0; //一旦出现了不是空格 则不再计算左边空格数据
            }
    	}
    	printf("左边空格有%d个\n",leftNumber);
        
        
    	/*计算字符串右边的空格数*/
        for(i=0;i<length;i++)
        {
    		if(string[i] == ' ' && string[i] != '\0')
            {
    			rightNumber++;
    		}
            else
            {
    			rightNumber = 0; 
            }
    	}
    	printf("右边空格有%d个\n",rightNumber);
        
        
        /*循环次数:字符串总长度 去掉左边的空格数 和 右边的空格数*/
        for(i=0;i<length-leftNumber-rightNumber;i++) 
        {
    		string[i] = string[i + leftNumber];  //有效的字符串往左移动 (左空格数)
        }
        
        string[length-leftNumber-rightNumber] = '#'; //为了方便好看出结果  在最后加上 # 号
        string[length-leftNumber-rightNumber+1] = '\0'; 
        printf("删除字符串的左边空格 和 右边空格结果 string:%s\n",string);
    	return 0;
    }
    
    
    输出结果:
    字符串长度为18
    左边空格有5个
    右边空格有7个
    删除字符串的左边空格 和 右边空格结果 string:he llo#
    
    

    关于函数传数组作为参数知识

    记住一点:函数传参数 过去只能 数组的首地址。而不是整个数组。

    #include <stdio.h>
    
    void aaa(int array[5])
    {
        printf("aaa函数结果\n");
        printf("%d\n",sizeof(array));//查看大小
        printf("%d\n",sizeof(array)/sizeof(array[0]));//查看个数
    }
    
    void bbb(int array[])
    {
        printf("bbb函数结果\n");
        printf("%d\n",sizeof(array));//查看大小
        printf("%d\n",sizeof(array)/sizeof(array[0]));//查看个数
    }
    
    
    int main()
    {
    	int array[5] = {1,2,3,4,5};
    	printf("main函数结果:\n");
        printf("%d\n",sizeof(array));//查看大小
        printf("%d\n",sizeof(array)/sizeof(array[0]));//查看个数
        aaa(array); //数组名就是地址 是数组第一个元素地址
        bbb(array);
        system("pause");
    	return 0;
    }
    
    
    输出结果:
    main函数结果:
    20
    5
    aaa函数结果
    4
    1
    bbb函数结果
    4
    1
    

    在Linux底下aaa,或bbb函数 sizeof(array)是8个字节。

    展开全文
  • 目录 ...这二者到底是什么呢? 数组指针:首先它是一个指针,指向一个数组,“指向数组的指针”。在32位系统下永远占4个字节,至于它指向的数组占多少个字节,只有在定义该指针时才知道。 指针数组

    目录

    • 数组指针与指针数组
    • 再谈array与&array的区别
    • array与&array的区别之讨论
    • array与&array的区别之总结
    • 参考

    1. 数组指针与指针数组
    在初学C语言时,很难分清楚数组指针和指针数组。这二者到底是什么呢?

    • 数组指针:首先它是一个指针,指向一个数组,“指向数组的指针”。在32位系统下永远占4个字节,至于它指向的数组占多少个字节,只有在定义该指针时才知道。
    • 指针数组:首先它是一个数组,数组的元素都是指针,“存储指针的数组”,数组占多少字节由数组本身决定。

    根据定义很好区分二者的关系,下面举一个例子,看看如何区分。

     -A)int *p1[10];   //int   *   p1[10];
     -B)int (*p2)[10]; //int *[10] p2;

    问题来了,(A)和(B)谁是指针数组,谁是数组指针呢?不急,可以这样来判别,同时也是以后在定义这二者的一个思路:

    • 符号之间的优先级问题:“[]”的优先级比”*”高,而“()”的优先级比“[]”高。

    • 因此,对于(A),p1与[]先结合,构成了一个数组的定义,数组名为p1(此时可以肯定的说:p1是一个数组了)。该数组的类型是int ,也就是说数组的每个元素是int 型,即为一个整型指针(此时可以肯定的说:数组的元素都是指针)。

    2. 再谈array与&array的区别
    在“数组名、取数组首地址的区别(一)”中,明确的指出array是数组首元素的首地址,&array是数组的首地址,其值相同而意义不同。由于数组指针的提出,下面看看这段代码:

    int main()
    {
        char array[5] = {'A','B','C','D'};
        char (*p3)[5] = &array;
        char (*p4)[5] = array;
        return 0;
    }
    • 对于p3和p4的使用,到底正确与否呢?
    • p3+1的值是什么?p4+1的值是什么?

    p3和p4是数组指针,都是指向一个数组。此处在定义的时候分别给赋予初值&array和array。array是数组首元素的首地址,&array是数组的首地址,其值相同而意义不同。

    注意,在C语言中,赋值号“=”号两边的数据类型必须是相同的。如果不相同就需要隐式或显示的类型转换。

    如果定义了一个指向数组的指针,那么这个指针指向的是这个数组的首地址,而非数组首元素的首地址(即使数组首元素的首地址与数组的首地址,其值相同,但是意义不同。)

    代码中,把&array(即数组的首地址)赋给p3,且“=”两边的数据类型是一致的,即此时p3就指向的是整个个数组。而把array(即数组首元素的首地址)赋给p4,p4的类型是指向整个数组的指针,而“=”右边的数据类型是指向单个字符的指针,即此时p4就指向的是一个数组首元素并非整个数组。

    当在VC++6.0上运行上段代码时,可发现编译器会提示警告:
    warning C4047: 'initializing' : 'char (*)[5]' differs in levels of indirection from 'char *'
    程序运行是没问题的。那么,下面继续讨论一下,在实际对其操作时,会产生什么样的结果呢?

    /**********************************************************************
    * File: array_name.c 
    * Copyright (C) jingzi123456789, All Rights Reserved! 
    * Description:  
    *   The difference between the array name and address of the array name 
    * Version: 1.0 
    * Date created: 11:28,29/03/2017 
    * Author: jingzi123456789 
    ***********************************************************************/
    #include <stdio.h>
    void main()
    {
        char array[5] = {'A','B','C','D'};
        char (*p3)[5] = &array;
        char (*p4)[5] = array;
    
        //char a[]="I love China!";
        //printf("sizeof(a)   = %d\n",sizeof(a));//计算后面的'\0'
        //printf("length(a)   = %d\n",strlen(a));//不计算后面的'\0'
    
        printf("array  = %p\n",array);
        printf("p3     = %p\n",p3);
        printf("&array = %p\n",&array);
        printf("p4     = %p\n",p4);
        printf("\n");
    
        printf("p3+1   = %p\n",p3+1);
        printf("p4+1   = %p\n",p4+1);
        printf("\n");
    
        printf("sizeof(* p3)    = %d\n",sizeof(* p3));
        printf("sizeof(* p4)    = %d\n",sizeof(* p4));
        printf("sizeof(p4)      = %d\n",sizeof(p4));
        printf("sizeof(array)   = %d\n",sizeof(array));//计算了后面的'\0'
        printf("length(array)   = %d\n",strlen(array));//不计算后面的'\0'
    
        return;
    }
    • 运行结果:
      这里写图片描述
    • 结果分析:
      (1)可以发现,p3和p4的值是一样的,p3和p4指向的内容的所占实际字节空间也是一样的。甚至是p3+1和p4+1的结果也是一样。
      (2)前面讲到:+1”就是偏移量问题:一个类型为T的指针的移动,是以sizeof(T)为移动单位。
      – 可以发现sizeof(p3)的结果是指针p3所占的字节空间。因此是4字节,而且对于任何类型的指针其所占内存大小固定不变的。

      • 提出一个小问题,sizeof()这个操作符(不是函数)到底是怎么实现的呢?

      –而sizeof(array)计算的是整个数组的空间大小,即在定义该数组时就决定了其内存空间的大小。
      (3)以p3为例,p3指向的数据类型是一个定义为占5个字节的字符型数组。根据偏移量规则,p3+1后的地址应该是元素array[4]的下一个地址值:0012FF40 + 1*sizeof(* p3)。

    下面画一个图,直观的感受一下:
    这里写图片描述

    (4)按照上述讨论的结果,p4虽然是一个数组指针,但是指向的是数组array首元素的首地址,即指向的是数组的第一个字符’A’。那么,p4+1为什么也会与p3的结果一样呢?

    3. array与&array的区别之总结
    详见:“数组名、取数组首地址的区别(一)”,“数组名、取数组首地址的区别(二)”。

    4.参考
    1.http://www.cnblogs.com/mq0036/p/3382732.html
    2.http://blog.chinaunix.net/uid-12779255-id-2916004.html
    3.《C语言深度解剖》——陈正冲

    展开全文
  • C语言数组名到底是什么

    千次阅读 2019-10-15 13:58:34
    C语言中数组名在表达式中被解读为指向数组首元素的指针, 即数组名在表达式中值为数组首元素的地址。(但有个例外,int a[2];int (*pa)[2]; pa=&a;此时a解读为指向数组的指针,而不是指向数组首元素的指针)。 ...
  • 数组指针 例如:int (*p)[10]; //解释:p先和* 结合,说明p一个指针变量,然后指着指向的一个...数组名代表的是数组首元素的地址 &数组名表示数组的地址,而不是数组首元素的地址 例如: #include<stdi...
  • 2)、将数组名看作常量指针传递数组首元素的地址 C语言以高效作为最初的设计目标: 1)、参数传递的时候如果拷贝整个数组执行效率将会大大降低 2)、参数位于栈上,太大的数组拷贝将导致栈的益出 二维数组参数 1、二...
  • C语言数组学习笔记(探讨) int arr[5]={1,3,5,7,9} int *p=arr int *pi[5]=&arr 其中指针p代表的数组arr的首地址 *(p+1)代表的就是第二个位置的3 p+1代表的第一个位置的值加1等于2 原因:由于’'的优先级...
  • 此操作表示创建一个可以存10个int型变量的数组a,而变量a实际上就是一个指针,它指向的是数组a首元素的首地址(也就是指向a[0]的首地址),我们通过a[1],a[2]…去寻找相应元素,实际上就是通过加上它距离首元素的...
  • 定义一个结构体数组 typedef struct { int a; float b; }Test_T; Test_T c[3];...c[0]有什么区别和联系呢?...c数值上等于整个数组首地址,在数值上与&c[0]相等,含义上代表整个数组所占内存的大小,其进阶单位
  • 浅谈C语言数组和指针

    2020-07-17 22:02:22
    首先,arr是数组名,而数组名就是指向数组第一个元素的指针,即数组名代表了这个数组首地址。 *p = arr就是直接将 arr 赋值给 p。 同时,数组地址是数组内第一个元素的地址。 *p1 = &arr 是获取
  • int sum(int marbles1[], int n)//如果此处marbles1指向元素地址的指针,主函数体中的调用函数中的marbles参量也应该指针,为什么主函数体中的marbles占字节大小16----即被认成了整个数组包含了4个整数 ...
  • 关于C语言数组的一些小细节

    多人点赞 2021-06-16 23:23:44
    既然数组传参传递的是首元素的地址,为什么函数的形参我们仍然可以写成数组的形式?(这样形参和实参是不是就不对应了呢?) 1.为什么数组下标从零开始 ? 先说说我的理解:[ ]这个操作符实际相等价于指针加减...
  • c语言中为什么数组名a,和&a的输出结果一样的,a不是本来就是地址
  • c语言数组指针的问题

    2014-01-24 20:01:03
    int zip[4] = {1,2,3,4};// 初始化一个数组 zip == &zip[0] // 这个没问题 那&zip 是什么意思 ?... // 这两个输出的值为什么一样 都是数组首元素的地址? 看指针和多维数组的时候搞糊涂了,现在一维的也有点懵。
  • 按照我一贯的理解, 一维数组名==元素地址==常量,理解马马虎虎,日常使用并没有什么问题 直到有一天我在思考一个左值右值的问题时,发现了数组名的不同 问题:既然数组常量,我们都知道常量不能当左值,所以...
  • 相信不少的C语言初学者都知道,数组名相当于指针,指向数组首地址,而函数名相当于函数指针,指向函数的入口地址。现在又这样一个问题,如果对数组名取地址,那得到的会是什么呢?很多人立刻会想到:给指针取地址...
  • 在C/C++中,数组名相当于一个指针,指向数组的首地址。这里“相当于”不代表等于,数组名和指针还是有很多区别的,这个在《C陷阱与...如果简单的认为arr就是一个指向数组首地址的指针的话,那么很自然会想到&a...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 192
精华内容 76
关键字:

c语言数组首地址是什么

c语言 订阅