指针进阶(三)

温故而知新

指针和数组笔试题解析

一维数组

int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));//16
//sizeof(a)是数组名单独放在sizeof内部,计算的数组总大小,单位是字节
printf("%d\n", sizeof(a + 0));//4/8
//a+0其实是数组首元素的地址
printf("%d\n", sizeof(*a));//4
//a是数组首元素的地址  - &a[0]
//*a - *&a[0]- a[0]
printf("%d\n", sizeof(a + 1));//4/8
//a是数组首元素的地址  int*
//a+1跳过一个整型,是第二个元素的地址
printf("%d\n", sizeof(a[1]));//4
printf("%d\n", sizeof(&a));//4/8
//&a-取出的是数组的地址,但是数组的地址也是地址,是地址大小就是4/8个字节
//int (*pa)[4] = &a;//int(*)[4]
printf("%d\n", sizeof(*&a));//16
//sizeof(a)
//int(*)[4]
printf("%d\n", sizeof(&a + 1));
//&a   int(*)[4]
//&a+1 跳过一个数组
printf("%d\n", sizeof(&a[0]));//4/8
printf("%d\n", sizeof(&a[0] + 1));//4/8

字符数组 

1.sizeof计算的是占用内存空间的大小,单位是字节,不关注内存中到底存放的是什么

2.sizeof不是函数,是操作符

3.strlen是函数

4.strlen是针对字符串的,求的是字符串的长度,本质上统计的是\0之前出现的字符个数

char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));//6
printf("%d\n", sizeof(arr+0));//arr+0是数组首元素的地址 4/8
printf("%d\n", sizeof(*arr));//*arr是首元素,计算的是首元素的大小 1 
printf("%d\n", sizeof(arr[1]));//1
printf("%d\n", sizeof(&arr));//&arr是数组的地址 4/8 
printf("%d\n", sizeof(&arr+1));//&arr+1    跳过一个数组后的地址  4/8
printf("%d\n", sizeof(&arr[0]+1));//4/8   第二个元素的地址 

printf("%d\n", strlen(arr));//随机值 因为不知道\0位置 
printf("%d\n", strlen(arr+0));//随机值 
printf("%d\n", strlen(*arr));//strlen只能接收的是地址        'a'  = 97  把97当成地址了    非法访问 
printf("%d\n", strlen(arr[1]));//'b' = 98 当成地址  形参非法访问 
printf("%d\n", strlen(&arr));//随机值  
printf("%d\n", strlen(&arr+1));//随机值 - 6 
printf("%d\n", strlen(&arr[0]+1));//随机值 - 1 


char arr[] = "abcdef";//[a b c d e f \0] 
printf("%d\n", sizeof(arr));//7
printf("%d\n", sizeof(arr+0));//4/8
printf("%d\n", sizeof(*arr));//是 数组首元素
// arr[0]   *(arr+0)
//int sz = sizeof(arr)/sizeof(*arr);
//int sz = sizeof(arr)/sizeof(arr[0]);
printf("%d\n", sizeof(arr[1]));//1
printf("%d\n", sizeof(&arr));//数组的地址  4/8
printf("%d\n", sizeof(&arr+1));//跳过一个数组   4/8
printf("%d\n", sizeof(&arr[0]+1));//4/8

printf("%d\n", strlen(arr));//6
printf("%d\n", strlen(arr+0));//6
printf("%d\n", strlen(*arr));//err
printf("%d\n", strlen(arr[1]));//err
printf("%d\n", strlen(&arr));//6
//&arr - char(*)[7]
printf("%d\n", strlen(&arr+1));//随机值 
printf("%d\n", strlen(&arr[0]+1));//5


char *p = "abcdef";
printf("%d\n", sizeof(p));//4/8
printf("%d\n", sizeof(p+1));//'b' 的地址 4/8 
printf("%d\n", sizeof(*p));//1
printf("%d\n", sizeof(p[0]));//*(p + 0 )   ==  'a'   1
printf("%d\n", sizeof(&p));//4/8  二级指针 
printf("%d\n", sizeof(&p+1));//  4/8     
//p == char*        &p ==  char**
printf("%d\n", sizeof(&p[0]+1));//4/8   'b'的地址 

printf("%d\n", strlen(p));//6
printf("%d\n", strlen(p+1));//5   p+1是'b'的地址 
printf("%d\n", strlen(*p));//err 
printf("%d\n", strlen(p[0]));//err
printf("%d\n", strlen(&p));//随机值 
printf("%d\n", strlen(&p+1));//随机值 与前者无关系 !!! 
printf("%d\n", strlen(&p[0]+1));//5

注意这三种写法的区别

char arr[] = {'a','b','c','d','e','f'};
char arr[] = "abcdef";//[a b c d e f \0] 
char *p = "abcdef";

二维数组

int a[3][4] = {0};//数组在内存中是连续存放的 

printf("%d\n",sizeof(a));// 48  a这个二维数组的数组名单独放在sizeof内部 ,计算整个数组的大小 
printf("%d\n",sizeof(a[0][0]));//第一行第一个元素    4个字节 
printf("%d\n",sizeof(a[0]));//16
//a[0]是第一行的数组名   这是数组名单独放在 sizeof内部  
//计算的是数组的大小 16   单位是字节 
printf("%d\n",sizeof(a[0]+1));//a[0]不是单独放在sizeof内部 ,a[0]表示首元素的地址  即第一行第一个元素的地址  &a[0][0]
//a[0]+1  是第一行第二个元素的地址  &a[0][1]
printf("%d\n",sizeof(*(a[0]+1)));//a[0][1]   大小4个字节 
printf("%d\n",sizeof(a+1));
//a作为二维数组的数组名并非单独放在sizeof内部,所以表示首元素的地址 
//二维数组的首元素是第一行 ,这里的a就是第一行的地址  int(*)[4]
//a+1 是跳过了第一行,指向了第二行  等价于&a[1] 
printf("%d\n",sizeof(*(a+1)));//16
//*(a+1) == a[1]
printf("%d\n",sizeof(&a[0]+1));
//&a[0]是第一行的地址
//&a[0]+1 是第二行的地址 
printf("%d\n",sizeof(*(&a[0]+1)));//16    a[1] 
printf("%d\n",sizeof(*a));//16    *a就是第一行    *(a+0)   a[0]
printf("%d\n",sizeof(a[3]));//16     不越界  因为没有真的访问 
printf("%d\n",sizeof(*arr+1));//4/8
//*arr  == arr[0]     arr[0]+1 ==> &arr[0][0] + 1 ==> &arr[0][1]

可通过下图来理解:

最后一行代码为什么不越界?可以看下面这个小例子

#include <stdio.h>
int main()
{
	int a = 5;
	short s = 11;
	printf("%d\n", sizeof(s = a + 2));//2  sizeof内部的表达式不会真的计算,通过类型可推断为2 
	printf("%d\n", s);//11
	return 0;
}

指针笔试题

笔试1

#include <stdio.h>
int main()
{
	int a[5] = { 1, 2, 3, 4, 5 };
	int* ptr = (int*)(&a + 1);
	printf("%d,%d", *(a + 1), *(ptr - 1));// 2 5
	return 0;
}
//程序的结果是什么?

笔试2

#include <stdio.h>
//由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
	printf("%p\n", p + 0x1);//加一 跳过20个字节   0x100014
	printf("%p\n", (unsigned long)p + 0x1);//变成整型  0x100001 整型加一
	printf("%p\n", (unsigned int*)p + 0x1);//0x100004   指针加一
	return 0;
}
  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值