数组名的意义
1.sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小
2.&数组名,这里的数组名表示整个数组,取出的是整个数组的地址
3.除此之外所有的数组名都表示首元素的地址
一维数组
#include<stdio.h>
int main()
{
//一维数组
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));//4*4=16
printf("%d\n", sizeof(a+0));//4/8 a+0是数组第一个元素的地址,是地址就是4/8个字节
printf("%d\n", sizeof(*a));//4 首元素地址解引用,就是第一个元素大小4
printf("%d\n", sizeof(a+1));//4/8 第二个元素地址大小
printf("%d\n", sizeof(a[1]));//4 第二个元素的大小
printf("%d\n", sizeof(&a));//4/8 &a取出的是数组的地址,是地址就是4/8
printf("%d\n", sizeof(*&a));//16 计算的是整个数组的大小
printf("%d\n", sizeof(&a+1));//4/8 &a是整个数组的地址,+1跳过整个数组,地址还是4/8
printf("%d\n", sizeof(&a[0]));//4/8 第一个元素的地址
printf("%d\n", sizeof(&a[0]+1));//4/8 第二个元素的地址
return 0;
}
总结是地址就是4/8,是个数就另外看。
*&a相当于a,表示这整个数组
字符数组
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));//6
printf("%d\n", sizeof(arr+0));//4/8 数组首元素地址
printf("%d\n", sizeof(*arr));//1 *arr是首元素,首元素是一个字符,大小是一个字节
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));//随机值 arr数组中没有\0,所以strlen函数会继续往后找\0,统计\0之前出现的字符个数
printf("%d\n", strlen(arr+0));//随机值 arr+0是数组首元素地址
//printf("%d\n", strlen(*arr));//err *arr是数组首元素,'a'-97,strlen函数非法访问
//printf("%d\n", strlen(arr[1]));//err 'b'-98,非法访问
printf("%d\n", strlen(&arr));//随机值 数组的地址
printf("%d\n", strlen(&arr+1));//随机值 跳过整个数组后的地址
printf("%d\n", strlen(&arr[0]+1));//随机值 第二个元素的地址
return 0;
}
总结:
sizeof是一个操作符
sizeof计算的是对象所占内存的大小,单位是字节
不管内存中存放的是什么,只在乎内存大小strlen 是一个库函数
求字符串长度,从给定的地址向后访问字符,统计\0之前出现的字符个数
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));//7
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
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
printf("%d\n", strlen(&arr+1));//随机值
printf("%d\n", strlen(&arr[0]+1));//5
return 0;
}
#include<stdio.h>
#include<string.h>
int main()
{
char *p = "abcdef";
printf("%d\n", sizeof(p));//4/8 p是指针变量,计算的是指针变量的大小
printf("%d\n", sizeof(p+1));//4/8 b的地址
printf("%d\n", sizeof(*p));//1 *p是元素a
printf("%d\n", sizeof(p[0]));//1 p[0]->*(p+0)->*p,首元素
printf("%d\n", sizeof(&p));//4/8 p在内存中的地址
printf("%d\n", sizeof(&p + 1));//4/8 &p+1是跳过p之后的地址
printf("%d\n", sizeof(&p[0] + 1));//4/8 b的地址
printf("%d\n", strlen(p));//6
printf("%d\n", strlen(p + 1));//5 从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
return 0;
}
二维数组
元素首地址是第一行地址
#include<stdio.h>
int main()
{
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));//48 计算的是整个数组的大小,单位是字节3*4*4=48
printf("%d\n", sizeof(a[0][0]));//4 第一行第一个元素的大小
printf("%d\n", sizeof(a[0]));//16 第一行的大小
printf("%d\n", sizeof(a[0]+1));//4/8 第一行第二个元素地址
printf("%d\n", sizeof(*(a[0]+1)));//4 第一行第二个元素
printf("%d\n", sizeof(a+1));//4/8 第二行地址
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 int[]4
return 0;
}
指针习题
1.a是首元素地址加1,第二个元素地址解引用就是2
&a+1是跳过整个数组,指向5后面,强制类型转换为int*
#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;
}
#include<stdio.h>
//结构体Test类型的变量大小是20个字节
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
int main()
{
p = (struct Test*)0x100000;
//%p 打印的是地址,打印32位比特位,但是用的是16进制展示的
//00000000 00000000 00000000 00000000 二进制
//00 00 00 00 十六进制
printf("%p\n", p + 0x1);//00100014 p是结构体指针,相加就是结构体指针大小
printf("%p\n", (unsigned long)p + 0x1);//00100001 强转成长整型,相加就是整型相加
printf("%p\n", (unsigned int*)p + 0x1);//00100004 整型指针+1,就是加4
return 0;
}
#include<stdio.h>
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);//%x 打印的是有效位数字 4,2000000
//ptr1[-1]=*(ptr1-1),int*(&a+1)指向的是4后面的一位
//
return 0;
}
#include<stdio.h>
int main()
{
int a[3][2] = { (0,1),(2,3),(4,5) };//()里面是逗号表达式,将()改成{}就不是逗号表达式了
int* p;
p = a[0];
printf("%d", p[0]);//p[0]=*(p+0);
return 0;
}
#include<stdio.h>
int main()
{
int a[5][5];
int(*p)[4];//指针数组
p = a;//p指向的是a的首元素地址
printf("%p,%d\n", &p[4][2] - &a[4][2] ,&p[4][2]- &a[4][2]);
//p[4][2]=*(*(p+4)+2)
return 0;
}
#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));
printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//10,5
return 0;
}
#include<stdio.h>
int main()
{
char* a[] = { "work","at","alibaba" };
char** pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
字符指针数组存的实际上是字符串首元素地址
二级指针pa指向a首元素地址,pa++跳过一个字节指向字符a,打印%s,将整个at 打印出