#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;
//}
C语言指针进阶(3)的代码笔记(初始版)
最新推荐文章于 2024-06-13 11:24:43 发布