[c语言基础知识整理]

本文详细介绍了C语言中的mallocfree内存管理,包括释放内存后置NULL的重要性,以及结构体对齐与大小的关系。同时,讲解了endif的使用、十六进制输出的格式控制以及自定义字符串拷贝和比较函数的实现。此外,还讨论了二维数组的偏移、数组指针的应用、指针函数返回值的限制以及函数指针数组的概念。最后,通过冒泡排序的示例展示了算法的实现过程。
摘要由CSDN通过智能技术生成

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因为局部变量仅在局部有效

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值