C语言指针进阶(3)的代码笔记(初始版)

#define  _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>

//
// strlen是库函数
// sizeof是关键字
//sizeof计算的是一个变量的类型属性,并不会真正的进行计算

数组和指针
数组 - 能够存放一组相同类型的元素,数组的大小取决于数组的元素个数和元素类型
指针 - 地址/指针变量,大小是4 / 8个字节
数组是数组,指针是指针,二者不等价
数组名是数组首元素的地址,这个地址可以存放再指针变量中
我们就可以使用指针来遍历数组

数组名
大多数情况下是数组首元素的地址
但是有两个例外:
sizeof(数组名[这里只能独自放一个数组名])  - 数组名表示整个数组,计算的是整个数组的大小
&数组名 - 数组名表示整个数组,取出的是整个数组的地址

//int main()
//{
//	//一维数组
//	int a[] = { 1,2,3,4 };
//	printf("%d\n", sizeof(a));// 16
//	printf("%d\n", sizeof(a + 0));// 4/8 这里的的数组名是数组首元素的地址 
//	printf("%d\n", sizeof(*a));// 4 // 这里的a是数组首元素的地址,*a得到的是 相当于a[0] 4
//	//*a -> *&a[0] -> a[0]
//	printf("%d\n", sizeof(a + 1));// 4/8 这里的a是数组首元素的地址,a + 1 得到的是第二个元素的地址,相当于 &a[1]
//	printf("%d\n", sizeof(a[1]));// 4 这里是数组的第二个元素
//	printf("%d\n", sizeof(&a));// 4/8 这里的&a是取出整个数组的地址,存放在一个数组指针中
//	//&a -> int(*)[4]
//	//&a+1 -- 跳过一个数组
//	printf("%d\n", sizeof(*&a));// 16 这里的*&可以互相抵消,就只剩下了a数组
//	printf("%d\n", sizeof(&a + 1));// 4/8 &a取出了a整个数组的地址,&a+1取得是向后跳过一个数组的地址
//	printf("%d\n", sizeof(&a[0]));// 4/8 这里等价于 &a
//	printf("%d\n", sizeof(&a[0] + 1));// 4/8 这里等价于 &a + 1
//	return 0;
//}



字符数组
//int main()
//{
//	char arr[] = { 'a','b','c','d','e','f' };
//	//printf("%d\n", sizeof(arr));// 6 计算的是arr数组的总大小
//	//printf("%d\n", sizeof(arr + 0));// 4/8 这里的arr是指数组首元素的地址
//	//printf("%d\n", sizeof(*arr));// 1 这里等价于*arr[0],取出的是'a'
//	//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 这里等价于&arr[1]
//
//	printf("%d\n", strlen(arr));//随机值  有点问题  因为strlen函数要找 '\0',这里不知道\0的位置
//	printf("%d\n", strlen(arr + 0));//随机值 这里的arr和上面的一样,都表示首元素的地址
//	printf("%d\n", strlen(*arr));//非法访问 *arr 这里得到的是'a',而strlen函数接受的参数类型为const char* str,但是这里是把字符a的ASCLL码值 -- 97给了strlen函数,strlen函数去访问97的这块空间,造成了非法访问
//	printf("%d\n", strlen(arr[1]));//非法访问 这里把'b'给了strlen函数,把'b' - 98当成地址,错误原因与上面相同(形参非法访问)
//	printf("%d\n", strlen(&arr));//随机值 
//	printf("%d\n", strlen(&arr + 1));//随机值 - 6
//	printf("%d\n", strlen(&arr[0] + 1));//随机值 - 1
//	return 0;
//}


字符串数组
//int main()
//{
//	char arr[] = "abcdef";
//	printf("%d\n", sizeof(arr));//7 字符串的结束标志是\0,sizeof计算的是内存大小
//	printf("%d\n", sizeof(arr + 0));//4/8
//	printf("%d\n", sizeof(*arr));//1
//	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 这里的arr是首元素的地址
//	printf("%d\n", strlen(arr + 0));//6
//	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));//5
//	return 0;
//}
//          正确
字符指针存储字符串
//int main()
//{
//	char* p = "abcdef";//字符串可以看作数组
//	printf("%d\n", sizeof(p));//4/8
//	printf("%d\n", sizeof(p + 1));//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
//	printf("%d\n", sizeof(&p[0] + 1));//4/8
//
//	printf("%d\n", strlen(p));//6
//	printf("%d\n", strlen(p + 1));//5
//	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));//5
//	return 0;
//}

//要是数组名是数组首元素的地址,就会发生降级

//int main()
//{
//	//二维数组
//	int a[3][4] = { 0 };//二维数组在内存中也是连续存放的
//	printf("%d\n", sizeof(a));//12*4 = 48  
//	printf("%d\n", sizeof(a[0][0]));//4
//	printf("%d\n", sizeof(a[0]));//16 这里是数组第一行,a[0]单独放在sizeof内部,计算的是a[0]整个第一行的大小
//	printf("%d\n", sizeof(a[0] + 1));//4/8 这里a[0]+1,没有单独放在sizeof中,a[0]表示&a[0][0], &a[0][0]+1 -- &a[0][1],即第一行第二列的地址
//	printf("%d\n", sizeof(*(a[0] + 1)));//4 这里是第一行第二列的元素
//	printf("%d\n", sizeof(a + 1));//4/8 这里是第二行数组的地址
//	//a作为二维数组的数组名并非单独放在sizeof内部,所以表示首元素的地址
//	//二维数组的首元素是第一行,这里的a就是第一行的地址 -- int (*)[4](数组指针)
//	//a+1 是跳过第一行,指向了第二行
//	printf("%d\n", sizeof(*(a + 1)));//16 这里是对第二行的地址解引用,得到的是第二行的元素
//	printf("%d\n", sizeof(&a[0] + 1));//4/8
//	printf("%d\n", sizeof(*(&a[0] + 1)));//16 这里得到的也是第二行的元素
//	printf("%d\n", sizeof(*a));//16 这里是第一行的元素
//	printf("%d\n", sizeof(a[3]));//16 这里是第四行的元素, 虽然这里没有第四行,但是sizeof并不关心是否有第四行,如果有的话大小就是16个字节
//	return 0;
//}



//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;
//}

//由于还没学习结构体,这里告知结构体的大小是20个字节
//在X86的环境下
struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}* p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
//在X86的环境下

//int main()
//{
//	p = (struct Test*)0x100000;
//	printf("%p\n", p + 0x1);//40 0x100014
//	printf("%p\n", (unsigned long)p + 0x1);// +1 因为被转换为 int 类型 0x100001
//	printf("%p\n", (unsigned int*)p + 0x1);// +4 因为+1 跳过了一个整形 0x100004
//	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       2 
	return 0;
}


//int main()
//{
//	int a = 5;
//	short s = 11;
//	printf("%d\n", sizeof(s = a + 2));//2 (short)
//	printf("%d\n", s);//是否等于7  //结果还是11
//	//原因是sizeof用的是类型属性进行计算的,没有真正的计算
//	return 0;
//}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值