一维数组、二维数组、字符数组的&、sizeof等操作

来源:互联网 发布:好听的翻唱知乎 编辑:程序博客网 时间:2024/06/05 21:10

   一 前提知识

1、sizeof是一个运算符,sizeof(a)计算的是a这种变量类型或结构体所占的字节数

2、变量名一旦进行了移位操作,那么他就退化成了指针

3、数组名和对数组名取地址的值是一样的,但是含义不一样

4、数组名和指针的区别

    指针是一个变量,变量的值是另外一个变量的地址。那么,既然指针是变量,那么指针必然有自己的存储空间,只不过是该存储空间内的值是一个地址值,而不是别的内容。
    数组名没有自己的空间。数组名仅仅是一个符号,不是变量,它没有自己的存储空间,而指针实实在在的是个变量,有自己的空间:数组名只是一个符号,不是一个变量,因此不能作为一个左值,因此不能被修改

      只有当数组名在表达式中使用时,编译器才会为它产生一个指针常量。而只有以下两种情况,才不被当做指针常量:

  • sizeof(数组名):返回数组长度(所占的字节数,不是数组元素个数),而不是指向数组的指针的长度。

  • &数组名:产生一个指向数组的指针,而不是一个指向某个指针常量的指针。

二 一维数组


关于一维数组明确一下几点:
1)数组名a是地址常量,他的值为a[0]的地址,所以a+i为a[i]的地址
2)对地址名取地址&a,虽然与a的值相同,但是含义不同,代表的是整个数组的地址。
3)a+1=a+sizeos(int),为a[i]的地址
      &a+1=a+sizeos(a),没有什么实际意义 
4)&a代表的是整个数组的地址。
      &(a+1)是错误的,因为&只能对变量取地址,但是a没有内存空间,a+1不知道赋给了那个变量,而且也没有实际意义
对一维数组取sizeof的问题总结:

要注意的是

1)sizeof(&a)的值是4,因为它的含义是一个指针;

2)变量名一旦进行了移位操作,那么他就退化成了指针所以a+1是指针的含义,所以为4

三 二维数组

在以为数组的基础上理解二维数组
A:数组名的理解
1)首先理解a与&a的区别
 a是二维数组的首地址,在值上等于&a,&a[0][0],*a

但是他们的值虽然相等,但是他们的含义不相同
a代表二维数组的第0行的地址,所以a+1是第1行的地址;
&a代表整个数组的地址,&a+1就把整个数组都越过去了;
*a代表的是第0行第0个的地址,含义相等于一维数组名;

2)a代表的其实是第0行的地址,因此a+i代表的是第i行的地址
     &(a+1)不仅是错误的而且是没有意义的
3)*(a+i)代表的是第i行第0列的地址;跟a[i]的意义一样,相等于数组名
   因此a[i]+1和*(a+i)+1代表的都是第i行第一列的地址
4)与一位数组类似
   a[i]的意义是第i行第0列的地址
& a[i]的意义是第一行这个内部数组的地址
 B:二维数组指针的理解
 attention:理解这些含义的关键在于:那些数组名的形式代表行地址,哪些代表列地址
其实要注意的是:a[0]和*a都是第0行第0列的地址,但是含义是一维数组名,所以对此去&,&a[0]和&(*a)其实相当于对一位数组名取&,转化成了行的地址

对二维数组取sizeof的相关含义:
     

int main99912()  {      int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};     int n=sizeof(a[0][0]);        printf("a=0x%x,*a=0x%x\n",a,*a);     printf("a size=%d,*a size=%d\n",sizeof(a),sizeof(*a));     printf("-------------------------------------------\n");
 
printf("a[0]=0x%x,*(a+0)=0x%x\n",a[0],*(a+0));      printf("a[0] size=%d,*(a+0)=%d\n",sizeof(a[0]),sizeof(*(a+0)));printf("-------------------------------------------\n");      
printf("&a[0]=0x%x,&a[0][0]=0x%x\n",&a[0],&a[0][0]);     printf("&a[0] size=%d,&a[0][0] size=%d\n",sizeof(&a[0]),sizeof(&a[0][0]));     printf("-------------------------------------------\n");     printf("a[1]=0x%x,a+1=0x%x\n",a[1],a+1);      printf("a[1] size=%d,a+1=%d\n",sizeof(a[1]),sizeof(a+1));   printf("-------------------------------------------\n"); 
        printf("&a[1][0]=0x%x,*(a+1)+0=0x%x\n",&a[1][0],*(a+1)+0);     printf("&a[1][0] size=%d,*(a+1)+0 size=%d\n",sizeof(&a[1][0]),sizeof(*(a+1)+0));     printf("-------------------------------------------\n");     printf("a[2]=0x%x,*(a+2)=0x%x\n",a[2],*(a+2));      printf("a[2] size=%d,*(a+2) size=%d\n",sizeof(a[2]),sizeof(*(a+2)));     printf("--------------------------------------- ---\n");     printf("&a[2]=0x%x,a+2=0x%x\n",&a[2],a+2);      printf("&a[2] size=%d,a+2 size=%d\n",sizeof(&a[2]),sizeof(a+2))
printf("-------------------------------------------\n");   
printf("a[1][0]=0x%x,*(*(a+1)+0)=0x%x\n",a[1][0],*(*(a+1)+0)); printf("a[1][0] size=%d,*(*(a+1)+0) size=%d\n",sizeof(a[1][0]),sizeof(*(*(a+1)+0)));     printf("-------------------------------------------\n");    return 0;      }   

解决上面需要注意的问题是:
1 数组名一旦进行移位操作他就退化成了指针
2

printf("a size=%d,*a size=%d\n",sizeof(a),sizeof(*a)); 

这句代码中,sizeof(a)表示整个二维数组的大小,*a表示*(a+0),所以,*a表示一维数组{1,3,5,7}的首地址,因此sizeof(*a)是4*sizeof(int)为16。

printf("a[0] size=%d,*(a+0)=%d\n",sizeof(a[0]),sizeof(*(a+0))); 

a[0]也就是*(a+0),和*a一样,也是指向一维数组{1,3,5,7}的首地址,因此a[0],*(a+0)用sizeof计算内存大小,是4*sizeof(int)为16 

printf("&a[0] size=%d,&a[0][0] size=%d\n",sizeof(&a[0]),sizeof(&a[0][0])); 

&a[0]就是&(*(a+0)),&和*互相抵消,因此相当于a+0,数组名参与了指针偏移运算,因此sizeof(&a[0])的大小为指针的内存小,是4字节。&a[0][0]就是&(*(*(a+0)+0)),&和*抵消以后,为*(a+0)+0,*(a+0)代表一维数组{1,3,5,7}的首地址,因此*(a+0)+0表示数组首地址参与偏移操作,成为指向数组{1,3,5,7}0号位元素1的指针,sizeof(&a[0][0])的大小为4字节。


四 字符串数组

1 一维数组对应的字符串
注意字符串带来的新特性:输出字符串的首地址,会输出整个字符串,所以效果如上图所示
1)为什么输出字符串的首地址,会输出整个字符串
无论是char*p="hello word"还是字符数组char p[]="12345",p均表示的是字符串的首地址,而cout<<p得到的都是整个字符串,C/C++规定当输出的字符串首地址时会输出整个字符串,直到遇到‘\0’.
所以需要注意的是当我们做一些面试题目的时候,处理字符串时,一定不要忘了字符串以‘\0’结尾的重要性
2)
[cpp] view plain copy
  1. #include "stdio.h"  
  2. char *get_string_1()  
  3. {  
  4.     char p[] = "hello world!";  
  5.     return p;  
  6. }  
  7. char *get_string_2()  
  8. {  
  9.     char *p = "hello world!";  
  10.     return p;  
  11. }  
  12. int main()  
  13. {  
  14.     char *p;  
  15.     p = get_string_1();  
  16.     printf("get_string_1:%s/n",p);  
  17.     p = get_string_2();  
  18.     printf("get_string_2:%s/n",p);  
  19.     return 0;  
  20. }  

输出:
get_string_1:(乱码或者没有输出,linux下没有任何输出)
get_string_2:hello world!
3)
char*p[ ]={"hello", word};
p是一个一维数组,内容是char类型的指针,因此不能通过p来改变内容,例如p[0][0]='r';


A:cout<<p——输出的是地址
B:cout<<*p——输出的是第一个字符串。*p相当于char*p中的p
C::cout<<**p——输出的是第一个字符串的第一个字符
2)p+1.p+2也是地址相当于第1个和第二个字符串的地址。
A:cout<<*(p+1)——输出的word
B:cout<<**(p+1)——输出的w
C:cout<<(*(p+1)+1)——输出的ord
D:cout<<*(*(p+1)+1)——输出的o
3)*p+1相当于char*p中的p中的p+1,指向了第一个字符串的第二个字符开始的字符串。
A:cout<<*p+1——输出的ello
B:cout<<*(*p+1)——输出的e
 2 二维数组对应的字符串
 
注意:在输出字符串时,当指针指向的是字符串的第一个字符的时候才会输出字符串,而所以上面当p+1表示第一行的地址,输出的是地址,不是字符串,只有*(p+1)代表p[1]代表第一行第0个字符地址,输出整个字符串

1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 牙根侧面有洞怎么办 牙齿长洞很大怎么办 两颗牙中间黑了怎么办 牙齿酸痛怎么办才能好 牙齿被磨小了疼怎么办 牙齿有黑点蛀牙怎么办 小孩有蛀牙牙痛怎么办 牙齿修补后疼痛怎么办 腹部绞痛出冷汗怎么办 结石运动后尿血怎么办 透析病人尿血该怎么办 宝宝吃药就吐怎么办 肚子坠胀尿血怎么办 透析病人回来血尿怎么办 血尿腹痛腰疼怎么办 新诺明 吃多了 怎么办 吃下火药拉肚子怎么办 打哈欠停不下来怎么办 小孩一直咳不停怎么办 孩子咳嗽咳不停怎么办 孩子咳嗽出冷汗怎么办 宝宝一直咳不停怎么办 尿血右上腹疼怎么办 尿道感染尿出血怎么办 儿童血尿腹痛是怎么办 肚子胀痛拉二天血尿怎么办 小牛肚尿道发炎怎么办 吃奶小牛涨肚怎么办 尿路感染尿出血了怎么办 尿血还带血块怎么办 尿道感染尿血了怎么办 老人小便带血怎么办 胎儿双肾盂扩张怎么办 宝宝发烧后血尿怎么办 孕妇肾盂分离16怎么办 急性尿道炎尿血严重怎么办 尿急尿频尿血严重怎么办 打预防针两天后发烧怎么办 孩子发烧心跳快怎么办 拉肚子脱水人犯困怎么办 拉肚子拉脱水了怎么办