【学习笔记之我要C】深入理解数组与指针

简介: 【学习笔记之我要C】深入理解数组与指针

一、前置提醒

sizeof()是一个单目操作符,用来计算数据长度,以字节为单位

 strlen是C语言标准库定义的一个函数,用来计算字符串的长度,直到空结束字符,但不包括空结束字符。查看源码我们可以知道,strlen要接收一个指针,也就是接收一个地址。

 数组名是数组首元素的地址,但是有2个例外:1.sizeof(数组名),这里数组名表示整个数组;2. &数组名,这里数组名表示整个数组,取出的是整个数组的地址。

二、一维数组

  先计算打印结果,然后在看后面的答案,笔试!!!不要直接复制到编译器上。

  1. 整形数组
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;
}
int main() {
  //以下都是32位机情况下的计算结果
  int a[] = { 1,2,3,4 };
  printf("%d\n", sizeof(a));
  //一个int类型占4个字节,4个int类型,打印结果为16
  printf("%d\n", sizeof(a + 0));
  //a作为数组名不是单独出现的,所以这里a表示首元素地址
  //首元素地址+0之后,还是首元素地址
  //一个地址的大小为4
  printf("%d\n", sizeof(*a));
  //a表示首元素地址,*a就是对首元素地址解引用,得到整型1
  //一个整型大小为4个字节
  printf("%d\n", sizeof(a + 1));
  //a + 1得到的是第二个元素的地址
  //一个地址的大小为4
  printf("%d\n", sizeof(a[1]));
  //a[1]取到的是第二个元素
  //int类型大小为4个字节
  printf("%d\n", sizeof(&a));
  //取到整个数组的地址,数组的地址也是地址
  //一个地址的大小为4
  printf("%d\n", sizeof(*&a));
  //&a取到的是整个元素的地址,解引用后得到整个数组
  //4个int类型,打印结果为16
  printf("%d\n", sizeof(&a + 1));
  //&a取到一个地址,地址+1后得到的还是一个地址
  //一个地址的大小为4
  printf("%d\n", sizeof(&a[0]));
  //操作符[]的优先级比&高
  //先a[0],表示数组的第一个元素
  //然后取地址&,取到第一个元素的地址
  printf("%d\n", sizeof(&a[0] + 1));
  //在取到第一个元素的地址上+1,得到第二个元素的地址
  return 0;
}
  1. 字符数组
int main() {
  char arr[] = { 'a','b','c','d','e','f' };
  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));
  return 0;
}
int main() {
  //以下都是32位机情况下的计算结果
  char arr[] = { 'a','b','c','d','e','f' };
  printf("%d\n", sizeof(arr));
  //一个char类型大小为1字节,6个char类型,打印6
  printf("%d\n", sizeof(arr + 0));
  //arr作为数组名不是单独出现的,所以这里arr表示首元素地址
  //首元素地址+0之后,还是首元素地址
  //一个地址的大小为4字节
  printf("%d\n", sizeof(*arr));
  //arr表示首元素地址,解引用后得到首元素
  //一个char类型大小为1字节
  printf("%d\n", sizeof(arr[1]));
  //表示第二个元素,一个char类型大小为1字节
  printf("%d\n", sizeof(&arr));
  //取的整个数组的地址,一个地址的大小为4字节
  printf("%d\n", sizeof(&arr + 1));
  //取到整个数组的地址,然后地址+1,得到另一个地址
  printf("%d\n", sizeof(&arr[0] + 1));
  //取到首元素的地址后+1,得到第二个元素的地址
  //注意:这里是strlen,不是sizeof了,不要继续用sizeof算(doge)
  printf("%d\n", strlen(arr));
  //strlen找到‘\0’才停下来,
  //但是arr并没有存储‘\0’
  //那么strlen会一直找下去,直到找到一个‘\0’为止
  //所以打印出来是一个随机值
  printf("%d\n", strlen(arr + 0));
  //arr+0得到首元素,
  //然后从首元素开始计算,结果发现怎么还是没有‘\0’
  //于是编译器又默默打印一个随机值
  printf("%d\n", strlen(*arr));
  //*arr解引用得到字符‘a’,
  //问题出现了,strlen只会接收地址
  //所以这行代码是错的
  printf("%d\n", strlen(arr[1]));
  //arr[1]得到字符‘b’,报错
  printf("%d\n", strlen(&arr));
  //&arr取到整个数组的地址,
  //BUT这个数组没有‘\0’,
  //于是编译器双默默打印一个随机值
  printf("%d\n", strlen(&arr + 1));
  //&arr + 1取到一个地址
  //BUT鬼知道‘\0’会在哪儿出现啊
  //于是编译器叒默默打印一个随机值
  printf("%d\n", strlen(&arr[0] + 1));
  //取到首元素地址之后+1,得到第二个元素
  //BUT第二元素也不知道‘\0’会在哪儿出现啊
  //于是编译器叕默默打印一个随机值
  return 0;
}
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));
  return 0;
}
int main() {
  //以下都是32位机情况下的计算结果
  char arr[] = "abcdef";
  printf("%d\n", sizeof(arr));
  //字符串在存储的时候会在最后加上‘\0’
  //sizeof不是strlen,它会计算‘\0’
  //所以7个char类型,打印7
  printf("%d\n", sizeof(arr + 0));
  //arr作为数组名不是单独出现的,所以这里arr表示首元素地址
  //首元素地址+0之后,还是首元素地址
  //一个地址的大小为4字节
  printf("%d\n", sizeof(*arr));
  //这里arr表示首元素地址,解引用后得首元素,一个char类型大小为1
  printf("%d\n", sizeof(arr[1]));//表示第二个元素,一个char类型大小为1
  printf("%d\n", sizeof(&arr));//整个数组的地址,一个地址大小为4
  printf("%d\n", sizeof(&arr + 1));//地址+1得到的还是地址,一个地址大小为4
  printf("%d\n", sizeof(&arr[0] + 1));//得第二个元素的地址,一个地址大小为4
  printf("%d\n", strlen(arr));
  //字符串在存储的时候会在最后加上‘\0’
  //strlen遇到‘\0’就停止,且不计算‘\0’
  //所以打印6
  printf("%d\n", strlen(arr + 0));
  //得到第一个字符的地址,开始计算长度,遇到‘\0’就停止,打印6
  printf("%d\n", strlen(*arr));//strlen要接收地址,报错
  printf("%d\n", strlen(arr[1]));//strlen要接收地址,报错
  printf("%d\n", strlen(&arr));//取整个数组的地址,打印6
  printf("%d\n", strlen(&arr + 1));
  //取整个数组的地址,+1跳过这个数组
  //这样就不知道哪里有‘\0’了
  //打印一个随机值
  printf("%d\n", strlen(&arr[0] + 1));//取到‘b’的地址,开始计算,结果为5
  return 0;
}

三、二维数组

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));
  printf("%d\n", sizeof(a[3]));
  return 0;
}
int main() {
  //二维数组
  int a[3][4] = { 0 };
  printf("%d\n", sizeof(a));
  //二维数组三行四列,都是int类型
  //3 * 4 * 4得48
  printf("%d\n", sizeof(a[0][0]));//第一行第一个元素,打印4
  printf("%d\n", sizeof(a[0]));
  //a[0]作为数组名单独放在sizeof内部,表示第一行
  //一行存放了4个int类型元素,得16
  printf("%d\n", sizeof(a[0] + 1));
  //a[0]没有单独放在sizeof内部,也没有取地址,表示第一行第一元素的地址,
  //+1得到第一行第二个元素的地址,一个地址大小为4
  printf("%d\n", sizeof(*(a[0] + 1)));//解引用得到第一行第二个元素,一个int类型大小为4
  printf("%d\n", sizeof(a + 1));
  //表示首元素地址,代表第一行
  //+1得第二行地址,一个地址大小为4
  printf("%d\n", sizeof(*(a + 1)));//解引用得到第二行数组,4个int类型大小为16
  printf("%d\n", sizeof(&a[0] + 1));//&a[0]取得第一行地址,&a[0] + 1得第二行地址,4
  printf("%d\n", sizeof(*(&a[0] + 1)));//对第二行地解引用,得第二行数组,4个int类型大小为16
  printf("%d\n", sizeof(*a));//a表示首元素地址,解引用得第一行数组,4个int类型大小为16
  printf("%d\n", sizeof(a[3]));
  //如果存在的话,a[3]表示第四行的数组名,
  //sizeof不需要它存在,推算出类型进行计算,4个int类型大小为16
  return 0;
}

四、指针

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));
  return 0;
}
int main() {
  char* p = "abcdef";
  printf("%d\n", sizeof(p));//p是一个指针,即地址,一个地址大小为4
  printf("%d\n", sizeof(p + 1));//地址+1得到的还是一个地址,大小为4
  printf("%d\n", sizeof(*p));
  //指针P存放的是首元素‘a’的地址
  //解引用得到元素‘a’
  //一个char类型的大小为1
  printf("%d\n", sizeof(p[0]));//p[0]相当于是对p进行解引用,得到元素‘a’,大小为1
  printf("%d\n", sizeof(&p));
  //指针也是一个变量,他也会开辟一个地址来存储
  //取p的地址得到的还是一个地址,大小为4
  printf("%d\n", sizeof(&p + 1));//地址+1得到的还是一个地址,大小为4
  printf("%d\n", sizeof(&p[0] + 1));
  //得到‘a’的地址后
  //再对‘a’取地址得到的还是一个地址
  //一个地址大小为4
  printf("%d\n", strlen(p));//p存放的是‘a’的地址,从‘a’开始计算,结果为6
  printf("%d\n", strlen(p + 1));//p+1后得到‘b’的地址,从‘b’开始计算,结果为5
  printf("%d\n", strlen(*p));//p解引用后得到‘a’,strlen要接收一个地址,报错
  printf("%d\n", strlen(p[0]));//p[0]相当于是对p进行解引用,得到元素‘a’,报错
  printf("%d\n", strlen(&p));
  //取到指针p的地址,从p的地址开始计算
  //但是不知道哪里会有‘\0’,所以打印出一个随机值
  printf("%d\n", strlen(&p + 1));//随机值
  printf("%d\n", strlen(&p[0] + 1));
  //p[0]相当于是对p进行解引用,得到元素‘a’
  //再对‘a’取地址,得到‘a’的地址,+1得到‘b’的地址
  //从‘b’开始计算,结果为5
  return 0;
}

就这?就这?就这?不就是两把头发的事情吗?

目录
相关文章
|
3天前
|
C语言
C语言:数组和指针笔试题解析(包括一些容易混淆的指针题目)
C语言:数组和指针笔试题解析(包括一些容易混淆的指针题目)
|
3天前
|
存储 编译器 C语言
函数指针&&数组指针&&数组传参的本质&&字符指针(进阶篇)
函数指针&&数组指针&&数组传参的本质&&字符指针(进阶篇)
|
3天前
|
存储 人工智能
指针的应用练习(数组与指针的关系)
指针的应用练习(数组与指针的关系)
12 0
|
3天前
|
存储 人工智能
字符指针变量和字符数组注意事项(区别)
字符指针变量和字符数组注意事项(区别)
7 0
|
3天前
指针的基础应用(数组的颠倒和排序,二维数组的表示)
指针的基础应用(数组的颠倒和排序,二维数组的表示)
7 0
数组指针、函数指针、指针数组、函数 指针数组、指针函数详细总结
数组指针、函数指针、指针数组、函数 指针数组、指针函数详细总结
|
3天前
指针指向数组
指针指向数组
17 0
|
3天前
|
存储 人工智能 C++
【重学C++】【指针】详解让人迷茫的指针数组和数组指针
【重学C++】【指针】详解让人迷茫的指针数组和数组指针
34 1
|
3天前
|
存储 C语言
指针数组作为main函数的形参
指针数组作为main函数的形参
14 0
|
3天前
|
C语言
指针数组以及利用函数指针来实现简易计算器及typedef关键字(指针终篇)
指针数组以及利用函数指针来实现简易计算器及typedef关键字(指针终篇)

热门文章

最新文章