malloc free 的使用
//释放地址后,还要有NULL这一步,否则造成悬空指针;
//free只是释放了那块空间,free之后,归还了地址的使用权,但是指针还保留着这块地址
#include<stdio.h>
2 #include<stdlib.h>
3 int main(int argc, const char *argv[])
4 {
5 int *p=(int *)malloc(sizeof(int));
6 printf("p=%p",p);
7 *p=100;
//在堆区申请一个int字节的空间
8 printf("*p=%d\n",*p);
9 int *q=(int *)malloc(100*sizeof(int));
10 printf("q=%p",q);
11 //在堆区申请100个int字节的空间
12 int i=0;
13 for(i=0;i<100;i++)
14 {
15 q[i]=i;
16 printf("%d\t",q[i]);
17 }
18 printf("\n");
19 free (p);
20 free (q);
21 printf("************\n");
22 printf("p=%p q=%p\n",p,q);
23 printf("************\n");
24
25 p=NULL;
26 q=NULL;
//释放地址后,还要有NULL这一步,否则造成悬空指针;
//free只是释放了那块空间,free之后,归还了地址的使用权,但是指针还保留着这块地址
27 printf("p=%p q=%p",p,q);
28 printf("\n");
30 return 0;
31 }
2、endif使用
#include<stdio.h>
int main(int argc, const char *argv[])
{
#if 0
printf("hhh"); //有条件执行,if 0 不执行此语句;if 1 执行此语句
#else
printf("333");
#endif
return 0;
}
3.%#x
int x=47; //47是十进制
printf("%x\n", x); //输出结果是: 2f
printf("%X\n", x); //输出结果是: 2F
printf("%#X\n", x); //输出结果是: 0X2F
printf("%#x\n", x); //输出结果是: 0x2f
4.struct 结构体对齐与结构体大小(首先找到结构体对齐字节数
结构体大小是对齐数的整数倍;
可以理解为,是按块存储,每一块如果能放下就放,放不下会再拿一块存放
结构体设置默认对齐的好处--------节省内存资源
#pragma pack(2) 设置默认对齐2字节对齐,(默认值必须是2的倍数,当默认大于缺省值,优先以缺省对齐)
#pragma pack() // 取消指定对齐,恢复缺省对齐
当结构体出现数组时,对齐大小还是以数据类型为准,而不是整个数组。
5.实现库函数字符串的拷贝,比较
#include <stdio.h>
char * stcat(char *a1,const char *a2)
{
assert(a1&&a2); //a1,a2不为空才能运行
char *p1=a1; //方便p1遍历到末尾\0位置
//char *p2=a2;
while((*p1)!='\0')
{
p1++;
}
while(*p1=*a2)
{
if(*a2=='\0') break;
p1++;
a2++;
}
// while(*p1++=*a2++)
// {
// ;
// }
return a1;
}
int stcmp(const char *s1, const char *s2)
{
while(*s1==*s2&&*s1!='\0'&&*s2!='\0')
{
s1++;
s2++;
}
return *s1-*s2;
}
int main(int argc, char const *argv[])
{
char s1[20]="hello";
char s2[]="hiXIXI";
//接收stcat返回值
char *arr=stcat(s1,s2);
printf("%s\n",arr);
printf("%d\n",stcmp(s1,s2));
return 0;
}
函数实现的注意事项:
strcat:不能自己给自己追加,因为‘\0’会被覆盖,函数因找不到‘\0’而无法结束
strcpy:不能拷贝无‘\0’结尾的数据;拷贝的目的空间要足够大才不至于越界;strcpy("abc","567"),错误----字符串作为常量不能被修改
6.二维数组偏移
a[3][4]------a+1偏移一行到a[1][0]-------**(a+1)取值
先 定位到行,再定位到列,如果访问某一个元素:
a+1第二行----*(a+1)第二行0列-----**(a+1)元素值
等价于===》*(a+1)[0]====》*(a[1]+0)------a+1,a[1]是第二行首元素地址
二维数组便于多个字符串的存放:char str[3][10]={"I","have","books"};-----str[1][0]=="have"
7.数组指针-应用----数组类型的指针int (*p)[4]中,有四个指针,分别指向二维数组的1234行
8.指针函数的返回值不可以是局部变量的地址(返回数值没问题)涉及内存分布回收问题
9.函数指针数组
#include <stdio.h>
int my_add(int x, int y){
return x+y;
}
int my_sub(int x, int y){
return x-y;
}
int main(int argc, const char *argv[])
{
//定义了一个函数指针数组
//数组中有两个成员 每个成员都是一个
//能指向 返回值为 int 形参列表为 (int, int) 的函数指针
int (*p[2])(int, int);
p[0] = my_add;
p[1] = my_sub;
int a = 10;
int b = 20;
//通过函数指针数组的成员调用函数
printf("%d\n", p[0](a, b));
printf("%d\n", p[1](a, b));
return 0;
}
10.冒泡排序
每一趟都比较出一个最值(最大,最小),5个数比较4趟就够了,
每一趟都是相邻两个数比较,比出来的最值不用再参加下一趟比较
#include<stdio.h>
2 int main(int argc, const char *argv[])
3 {
4 int a[5]={9,4,8,3,2};
5 int i,j,temp;
6 for(i=0;i<4;i++)
7 {
8 for(j=0;j<5-i;j++)
9 {
10 if(a[j]>a[j+1])
11 {
12 //temp=a[j];
13 //a[j]=a[j+1];
14 //a[j+1]=temp; //------三杯水交换
15 a[j]=a[j]^a[j+1]; //-----异或交换(相同为0,不同为1
16 a[j+1]=a[j]^a[j+1];
17 a[j]=a[j]^a[j+1];
18 }
19 }
20 }
21 for(i=0;i<5;i++)
22 {
23
24 printf("a[i]=%d ",a[i]);
25 }
26 printf("\n");
27 return 0;
28 }
对数组名取地址表示,整个数组的地址,而数组名仅表示第一个元素的地址,所以&a+1与a+1意义不同,&a+1会加上一个数组的大小,而a+1表示数组第二个元素的地址。
运行结果:0,41因为局部变量仅在局部有效