C语言指针练习

指针练习

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

int* ptr = (int* ) ( &a + 1) ;

printf ( "%d,%d",* (a + 1), * (ptr - 1) );		//2,5

解释:&a取出一整个数组的地址,+1后跳到数组最后一个元素的后一个地址,类型是int(*)[5],是数组指针的类型,需要强制类型转换为int,才能赋给指针ptr,ptr-1到下标为4的元素,解引用得到元素5,a是首元素地址,+1得到第二个元素地址,解引用得到2

考察的是:指针类型决定了指针的运算!

这里结构体的大小是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);		//0x100014		+0x1就是+1,因为p指向的是结构体,大小为20个字节,所以这里的+1是指+20个字节,跳过一个结构体类型,20的十六进制是14,所以结果是0x100014
	
	printf("%p\n",(unsigned long)p + 0x1);		//0x100001		指针p强制类型转换为了整型,所以加1就是1

	printf("%p\n",(unsigned int *)p + 0x1);		//0x100004		指针p强制类型转换为了整型指针类型,指针类型+1,跳过的是该类型所占字节数的大小,所以这里的+1是跳过4个字节

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

	int* ptr1 = (int*) (&a + 1);

	int* ptr2 = (int*)((int)a + 1) ;

	printf("%x,%x", ptr1[-1], *ptr2) ;		//4,2000000

	return 0;
}

在这里插入图片描述

解释:&a取出整个数组的地址,+1后到最后一个元素的后一块地址,ptr1指针就指向这里,输出ptr1指针时,ptr1[-1] == (ptr+(-1)) == * (ptr-1),所以-1后ptr1就指向元素4的起始地址,因为是int类型,访问4个字节,因为在小端存储模式下,数据低位在低地址,数据高位在高地址,所以读出来是00000004,就是4 ;

a指向首元素的地址,(int)a则将十六进制的地址强制类型转换为了整型,再+1,然后再转回指针类型,如0x0012ff44 --> int+1 -->0x0012ff45,因为地址都是相隔一个字节存放的,所以ptr2指向了01后一块地址,输出时解引用向后访问4个字节,因为小端存储,所以输出是02000000,即2000000

如果想要输出结果有0x,输出格式可写为:%#x

int main()
{
	int a [3][2]= {(0,1), (2,3),(4,5)};
	int* p;
	p = a[0];
	printf ("%d", p[0]);		//1
	return 0;
}

解释:这道题的重点不在于指针p,而是二维数组的初始化,二维数组正确初始化的话里面应是大括号,而现在使用的是小括号,小括号括起来的是一个逗号表达式,只取最后一个元素的值,所以该数组初始化的结果为

在这里插入图片描述

p[0] == *(p+0) == *p,而指针p指向首元素的地址,所以输出1

int main()
{
	int a[5][5];
	int (*p)[4];
	p = a; 		//p:int(*)[4]  - > a:int(*)[5];
	printf ("%p, %d\n",&p[4][2] - &a[4][2],&p[4][2] - &a[4][2]);	//FFFFFFFC,-4
}

解释:二维数组a是5行5列的,而数组指针p访问时是以4个元素为单位进行,虽然在p = a时会有警告类型不匹配,但指针p仍然指向数组a的首元素地址,分别找到a[4] [2]的地址和p[4] [2]的地址,如图所示,发现不是同一块地址,而地址相减的结果是地址之间元素的个数,而由因为是低地址减去高地址,所以是-4;

-4的原码:1000 0000 0000 0000 0000 0000 0000 0100

​ 反码:1111 1111 1111 1111 1111 1111 1111 1011

​ 补码:1111 1111 1111 1111 1111 1111 1111 1100

因为-4在内存中是以补码形式保存的,当以%p形式打印时,编译器会把-4看成一个地址,因为地址没有负数,所以将-4的补码转为十六进制就是FFFFFFFC

补码:1111 1111 1111 1111 1111 1111 1111 1100

因为-4在内存中是以补码形式保存的,当以%p形式打印时,编译器会把-4看成一个地址,因为地址没有负数,所以将-4的补码转为十六进制就是FFFFFFFC

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值