目录
1. sizeof和strlen的对比
1.1 sizeof
sizeof是用来计算变量所占内存空间的大小,单位:字节。
如果操作数是类型的话,计算的是使用类型创建的变量所占内存空间的大小。
(sizeof 只关注占用空间的大小,不在乎内存中放了什么)
1.2 strlen
strlen 是用来求字符串长度的。
size_t strlen ( const char * str );
strlen 统计的是字符串开始到 \0 之前的字符串的字符个数。(strlen 找到 \0 就会停止,没有找到就会一直找下去)
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[3] = { 'a', 'b', 'c' };//没有\0
char arr2[] = "abc";//a,b,c,\0
printf("%d\n", strlen(arr1));//随机数
printf("%d\n", strlen(arr2));
return 0;
}
1.3 sizeof和strlen 的对比
sizeof | strlen |
1. sizeof 是操作符 2. sizeof 计算操作数所占内存的大小,单位:字节 3. 不管内存中存什么数据 | 1. strlen 是库函数,使用时需要包含头文件<string.h> 2. strlen 是求字符串长度的,统计的是\0 之前字符的间隔个数 3. 关注内存中是否有 \0 如果没有 \0 ,就会持续往后找,可能会越界。 |
2. 数据和指针题解析
首先我们先来补充一个知识点
数组名:数组名一般表示数组首元素的地址,但是有2个例外,
1. sizeof(数组名),数组名表示整个数组,计算的是整个数组的大小,单位是字节;
2. &数组名,数组名表示整个数组,取出的数组的地址;
除此之外,所有遇到的数组都是数组首元素的地址。
2.1 一维数组
int main()
{
int a[] = { 1,2,3,4 };//a数组有4个元素,每个元素是int类型的数据
printf("%d\n", sizeof(a));//计算的是整个数组的大小---16
printf("%d\n", sizeof(a + 0));//计算的是首元素地址+0,也就是首元素地址,——4或8
printf("%d\n", sizeof(*a));//计算的是首元素的大小--4
printf("%d\n", sizeof(a + 1));//计算的是首元素地址+1,也就是第二个元素地址的大小,——4或8
printf("%d\n", sizeof(a[1]));//计算的是下标为1的元素大小——4
printf("%d\n", sizeof(&a));//&a—取出的是数组地址,但是数组地址也是地址,所以——4或8
printf("%d\n", sizeof(*&a));//计算的是整个数组的大小——16
printf("%d\n", sizeof(&a + 1));//&a—取出的是数组地址,&a+1是跳过整个数组后的地址,也是地址——4或8
printf("%d\n", sizeof(&a[0]));//&a[0]是第一个元素的地址--4或8
printf("%d\n", sizeof(&a[0] + 1)); //&a[0] + 1是第二个元素的地址——4或8
return 0;
}
2.2 字符数组
2.2.1
int main()
{
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));//计算的是数组的第一个元素的地址——1
printf("%d\n", sizeof(arr[1]));//计算的是数组下标为1的元素——1
printf("%d\n", sizeof(&arr));//&arr是整个数组的地址,但是数组地址也是地址——4或8
printf("%d\n", sizeof(&arr + 1));//&arr—取出的是数组地址,&arr+1是跳过整个数组后的地址,也是地址——4或8
printf("%d\n", sizeof(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址——4或8
return 0;
}
2.2.2
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));//随机值
printf("%d\n", strlen(arr + 0));//随机值
printf("%d\n", strlen(*arr));//访问错误,*arr是‘a’-97
printf("%d\n", strlen(arr[1]));//访问错误,arr[1]是'b'
printf("%d\n", strlen(&arr));//随机值
printf("%d\n", strlen(&arr + 1));//随机值
printf("%d\n", strlen(&arr[0] + 1));//随机值
return 0;
}
2.2.3
int main()
{
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));//arr+0是数组的首元素地址,地址的大小——4/8
printf("%d\n", sizeof(arr + 0));//
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[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));
return 0;
}
2.2.4
#include<string.h>
int main()
{
char arr[] = "abcdef";
printf("%d\n", strlen(arr));//6
printf("%d\n", strlen(arr + 0));//arr+0是数组首元素的地址:6
printf("%d\n", strlen(*arr));//err 传递的是'a'
printf("%d\n", strlen(arr[1]));//err 传递的是'b'
printf("%d\n", strlen(&arr));//err
printf("%d\n", strlen(&arr + 1));//随机值
printf("%d\n", strlen(&arr[0] + 1));//&arr[0] + 1是第二个的地址--5
return 0;
}
2.2.5
int main()
{
const char* p = "abcdef";
printf("%d\n", sizeof(p));//计算的是指针变量的大小-4/8
printf("%d\n", sizeof(p + 1));//p+1是’b‘的地址
printf("%d\n", sizeof(*p));//'a'---1
printf("%d\n", sizeof(p[0])); //p[0]=='a'---1字节
printf("%d\n", sizeof(&p));//&p-是自己的地址--4/8
printf("%d\n", sizeof(&p + 1));//4/8
printf("%d\n", sizeof(&p[0] + 1));//(&p[0] + 1)是'b'的地址
return 0;
}
2.2,6
int main()
{
const char* p = "abcdef";
printf("%d\n", strlen(p));//6
printf("%d\n", strlen(p + 1));//5
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
return 0;
}
2.3 二维数组
int main()
{
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));//12*4=48个字节,数组名单独在sizeof内部
printf("%d\n", sizeof(a[0][0]));//4
printf("%d\n", sizeof(a[0]));//是第一行这个一维数组的数组名,数组名单独放置sizeof内部了--16
printf("%d\n", sizeof(a[0] + 1));//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是数组首元素的地址,应该是第一行的地址,a+1是第二行的地址----4/8
printf("%d\n", sizeof(*(a + 1)));//第二行的数组名,计算的是第二行的大小--16
printf("%d\n", sizeof(&a[0] + 1));///&a[0]是第一行的地址,&a[0]+1就是第二行的地址
printf("%d\n", sizeof(*(&a[0] + 1)));//对第二行的地址解引用,计算的是第二行的大小--16
printf("%d\n", sizeof(*a));//这里的a是第一行的地址,*a就是第一行---16
//*a->*(a+0)--.a[0]
printf("%d\n", sizeof(a[3]));//a[3]就是的是第四行的大小---16
//因为sizeof内部的不都是不会真实计算
return 0;
}
3. 指针运算题解析
3.1 例1
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int* ptr = (int*)(&a + 1);
printf("%d,%d", *(a + 1), *(ptr - 1));
return 0;;
}
运行结果:
3.2 例2
//在X86环境下
//假设结构体的⼤⼩是20个字节
//程序输出的结构是啥?
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}*p = (struct Test*)0x100000;
//指针+整数
int main()
{
printf("%p\n", p + 0x1);//0x100000+20=0x100014
printf("%p\n", (unsigned long)p + 0x1);//0x100001
printf("%p\n", (unsigned int*)p + 0x1);//ox100004
return 0;
}
3.3 例3
#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };//里面的括号是小括号,所以表示的逗号表达式
//所以真正的数组元素是1,3,5,其他都是0
int* p;
p = a[0];
printf("%d", p[0]);
return 0;
}
3.4 例4
//假设环境是x86环境,程序输出的结果是啥?
#include <stdio.h>
int main()
{
int a[5][5];//int (*ptr)[5]=a
int(*p)[4];//P是数组指针,指向的数组4个类型的元素
p = a;
printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);//指针-指针点决斗者得到的是指针和指针之间的元素个数,FFFFFC,-4
return 0;
}
3.5 例5
#include <stdio.h>
int main()
{
int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int* ptr1 = (int*)(&aa + 1);
int* ptr2 = (int*)(*(aa + 1));//a[1]//aa是首元素的地址,也就是第一行的地址,aa+1就是第二行的地址
printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//10,5
return 0;
}
3.6 例6
#include <stdio.h>
int main()
{
const char* a[] = { "work","at","alibaba" };//指针数组
char** pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
3.7 例7
#include <stdio.h>
int main()
{
const char* c[] = { "ENTER","NEW","POINT","FIRST" };
const char** cp[] = { c + 3,c + 2,c + 1,c };
const char*** cpp = cp;
printf("%s\n", **++cpp);//POINT
printf("%s\n", *-- * ++cpp + 3);//ER
printf("%s\n", *cpp[-2] + 3);//ST cpp[2]-->*(cpp-2)
printf("%s\n", cpp[-1][-1] + 1);//EW cpp[-1][-1]-->*(*(cpp-1)-1)+1
return 0;
}