结合上一章节的博文 http://blog.csdn.net/hucblog/article/details/44940617
我们在进行下部分的复习
1.指针高级
1.1指针定义
1.1.1 指针数组
首先我们定义一个整型数组
int array[6];
整型数组,数组中的每个元素都是一个整型元素
那么,推算出指针数组的定义
int* array[6];
指针数组,数组中的每个元素都是一个指针
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *p[]={"hello","world","nice","fuck"};
int i;
for (i = 0; i < 4; i++)
{
printf("%p\t%s\n",p[i],p[i]);
}
system("pause");
return 0;
}
如上代码:
上图是在ubuntu测试的,在windows平台下,Ro.Data区的地址并不是连续的,这很纠结
在Ubuntu中64位编译,指针在栈中占有8个字节,在32位中占4字节,所以这里使用sizeof(p) 得到的结果有16或32两种可能
1.1.2二重指针
二重指针是指向指针的指针
1.1.3 数组指针
数组指针是一个指针,指向的是一个数组
我们定义一个int行的指针是这么定义的
int *p;
那么定义一个指向int行数组的指针,
int (*p)[10]
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
char arr[3][10]={"nice","hello","sorry"};//定义一个二维数组
char (*p)[10];//定义一个数组指针,相当于二维数组的行指针
p=&arr[0];//将二维数组的第0行给数组指针p
for (i = 0; i < 3; i++)
{
printf("%s\n",*(p+i));
}
system("pause");
return 0;
}
上续代码是数组指针和二维数组结合的使用方式
1.1.4 函数指针
这个指针指向的是一个函数,定义如下int (*p)(int,int);
应用:
#include <stdio.h>
#include <stdlib.h>
int add(int a,int b)
{
return a+b;
}
int sub(int a,int b)
{
return a-b;
}
int mul(int a,int b)
{
return a*b;
}
int division(int a,int b)
{
return a/b;
}
int computing(int (*p)(int,int),int a,int b)
{
return p(a,b);
}
int main()
{
printf("a=9\tb=3\nadd=%d\tsub=%d\tmul=%d\tdivision=%d\n",computing(add,9,3),computing(sub,9,3),computing(mul,9,3),computing(division,9,3));
system("pause");
return 0;
}
1.2 指针加1
1.2.1 指针数组加1
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *p[3]={"nice","mono","sheit"};
int i;
//p是一个数组,数组里有三个字符串指针
//sizeof(p) 其实就是数组的大小 在32位中指针占4字节 所有此时是4*3=12 64位系统则是8*3=24
//sizeof(*p) *p可以看我p[0] 取出来的是一个指针 所以在32位系统中是4 64位系统中是8
//那么p+1 就是加过一个指针 4个字节
printf("sizeof(p)=%d\tsizeof(*p)=%d\n",sizeof(p),sizeof(*p));
for (i = 0; i < 3; i++)
{
printf("%s\n",*(p+i));
}
//总结:p是数组,数组每个元素又是指针,所以指针数组和二重指针对等
system("pause");
return 0;
}
1.2.2 二重指针加1
#include <stdio.h>
#include <stdlib.h>
int main()
{
char **p;
//p是一个指向指针的指针,其实还是个指针
//sizeof(p) p是指针,所以为4
//sizeof(*p) 取值*p还是指针 所以为4
//那么p+1就加过4个字节
printf("sizeof(p)=%d\tsizeof(*p)=%d\n",sizeof(p),sizeof(*p));
system("pause");
return 0;
}
1.2.3函数指针加1
函数指针加1是没有意义的,函数指针也是指针 所以sizeof(p)是4
1.2.4 数组指针
#include <stdio.h>
#include <stdlib.h>
int main()
{
char (*p)[10];
//p是一个指针
//sizeof(p) p是指针,所以为4
//sizeof(*p) 取值*p是数组,数组有10个char元素 所以为10
//那么p+1就加过一个数组,10个字节
printf("sizeof(p)=%d\tsizeof(*p)=%d\n",sizeof(p),sizeof(*p));
system("pause");
return 0;
}
最后,指针数组就是二重指针,数组指针就是二维数组
2.typedef
typedef 给类型取一个别名,作用:
1.封装了数据类型,方便移植 2.简化函数指针的定义
2.1 typedef和define的区别
#include <stdio.h>
typedef char* newtype1;
#define newtype char*
int main()
{
newtype1 p1,p2;
p1="hello";
p2="world";
return 0;
}
使用typedef时 p1和p2 都是指针。 使用define则p1是指针 p2是char 因为define定义的 在编译期间自行展开 最终编译就是 char *p1,p2; typedef 则是char *p1,char *p2;
3.结构体
3.1 结构体的优化
未优化:
#include <stdio.h>
struct Student
{
int id; //4
char sex;//1
int score;//4
char name[20];//20
char blood;//1
};
int main()
{
struct Student s1;
//sizeof 大小是36 4+1+4+20+1=30
// 结构体4字节对齐 sex 在两整型之间 因为需要对齐 所以也被看成4字节 及 4+4+4+20+1=33 最终是36
printf("sizeof(Student)=%d\n",sizeof(struct Student));
getchar();
return 0;
}
优化:
#include <stdio.h>
struct Student
{
int id; //4
int score;//4
char name[20];//20
char blood;//1
char sex;//1
};
int main()
{
struct Student s1;
//sizeof 大小是32 4+4+20+1+1=30
// 结构体4字节对齐 最终是32
printf("sizeof(Student)=%d\n",sizeof(struct Student));
getchar();
return 0;
}
可以看出节省了4个字节。
总结,结构体中的成员尽量相同类型的放在一块
4.动态内存分配
4.1 malloc和free
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int *p=(int *)malloc(100);//向堆中申请100个字节
int i;
memset(p,0,100);//初始化这100个字节为0
for ( i = 0; i < 25; i++)
{
printf("%d\n",p[i]);
}
//p++;//如果p不是首地址,释放时会出错
free(p);//释放堆内存,p的地址不能改变 否则释放出错
getchar();
return 0;
}
可以使用malloc解决,数组不能动态分配大小的问题
scanf("%d",&i);
int *p=(int *)calloc(i,sizeof(int));