C语言进阶(二)

1.结构体

结构体是一些值得集合,这些值称之为成员变量。结构体得每个成员变量可以是不同类型得变量。

#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>

struct Student{
  char name[20];
  int  age;
  char sex[10];
} Stu;//全局变量

struct //匿名结构体类型,只能使用一次。 且声明得指针类型不能获取地址p=&s2是非法得
{
  char name[20]
}s2,*p;

int main()
 {
  struct Student s1;//局部变量
   Stu.name="cfh";
   Stu.age=20;
   Stu.sex="male";
    s1={"abc",12,"female};//初始化
   system("pause");
   return 0; 
 };

结构体的自引用

#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
//链表的自引用
struct Node0{
  char name[20];
  int  age;
  struct Node0 next;
} ;//链表错误示范1  -> sizeof无法计算大小

typedef struct 
{
 int age;
  Node1* pp;
}Node1;//链表错误示范2  -> 非法,矛盾

struct Node{
  char name[20];
  int  age;
  struct Node *next;
} ;//链表正确示范1   最后一个链表指针置空->NULL   
typedef struct  Node2
{
  int age;
  Node3* ptr;
}Node3;//链表正确示范1

int main()
 {

   system("pause");
   return 0; 
 };

3.结构体内存对齐

#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<stddef.h> 
//结构体大小不仅跟内部数据类型大小相关,还跟顺序相关
struct Node0{
  char c1;//1byte
  int  age;//4byte
  char c2;//1byte
}s1,s2;//大小12

struct Node1{
  char c1;//1byte
  char c2;//1byte
  int  age;//4byte
}s3,s4;//大小8

int main()
 {

  printf("%d\n",offsetof(struct  Node1,c1));//->需要引入stddef.h头文件
  printf("%d\n",offsetof(struct  Node1,c2));
  printf("%d\n",offsetof(struct  Node1,age));
  printf("%d\n",sizeof(s1));
  printf("%d\n",sizeof(s3));
  system("pause");
  return 0; 
 };

4.结构体传参

5.位段:位段的声明与结构体类似,有两个不同(1).位段的成员必须是int,unsigned int 或者signed int,(2).位段的成员名后面有一个冒号和一个数字。

#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
struct A{//A是一个位段类型->用以节省空间的
  int _a:2;//意思是_a只给2个bit位
  int _b:3;//意思是_b只给3个bit位   ->以int 的4个字节位单位步进增加
  int _c:10;
} s1;
int main()
 {
  printf("%d\n",sizeof(struct A));//->4个byte
  system("pause");
  return 0; 
 };

每一次开辟出来的空间占用后若未使用完,下一个元素的内存若大于剩下的空间,则需重新开辟空间,多余的空间空置。

6.枚举 :把可能的值一一列举

#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
enum NUM{//默认从零开始计数加一,可以赋初值
ADD=1,
DEL,
SUB,
PRO
};
int main(){
  int input;
  scanf("%d",&input);
  switch(input){
    case ADD: printf("ADD");break;
    case DEL:printf("DEL");break;
    case SUB:printf("SUB");break;
    default :printf("PRO");break;
  };
  system("pause");
}

#define 与enum之间的区别

7.联合(共用体) :一种特殊的自定义类型,包含一系列的成员,特征是这些成员公用一块空间。

#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
struct Student{
  int a;
  char c;
};
union Un{
  int a;
  char c;
};
int main(){
  union Un u;

  printf("%d\n",sizeof(u));
 printf("%p\n",&u);
 printf("%p\n",&(u.c));
 printf("%p\n",&(u.a));
  system("pause");
}

union Un{
    char arr[5];//5->char 对应的对齐数为1   最大成员内存为5.但应该是最大对齐数的整数倍,故为8
    int a;//4            对齐数为4   
};//占用空间8

8.动态内存开辟:

#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<error.h>
#define INMAX 0xFFFFFFFF


//          C99标准支持的变长数组
//变长数组->int n=0;scanf("%d",&n);
//          int arr[n];
int main(){
  int a[10]={0};
  //动态内存开辟
  int *p=(int*)malloc(40);
  if(p==NULL)
    {
      printf("%s\n",strerror(errno));//->引入error.h文件
      return 1;
    }
  /*申请内存过大错误案例
    int *p=(int*)malloc(INMAX);
  */
  //使用
  int i=0;
  for (;i<10;i++){
    *(p+i)=i;
  } 
  for (i=0;i<10;i++){
    printf("%d\n",*(p+i));
  } 
  //没有free 并不是说内存空间不回收了 当程序退出的时候,系统会自动回收内存空间
  //内存泄漏:内存一直不释放且倍占据,相当于丢失了这一部分。
  free(p);//->p指向的位置不变,但是里面的东西置空了
  p=NULL;//->置空,让其找不到原始的地址和数据
  system("pause");
  return 0;
}

#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<error.h>
#define INMAX 0xFFFFFFFF

int main(){
  int a[10]={0};
  //动态内存开辟
  int *p=(int*)malloc(40);
  if(p==NULL)
    {
      printf("%s\n",strerror(errno));//->引入error.h文件
      return 1;
    }
  //使用
  int i=0;
  for (;i<10;i++){
    *(p+i)=i+1;
  } 
  for (i=0;i<10;i++){
    printf("%d\n",*(p+i));
  } 
  //扩容->根据情况判断是否->开辟新的空间存储然后释放原有的空间或者在后面直接添加
  int* ptr=(int*)realloc(p,80);//不能直接将扩容的对象返回的值直接返回给自身,若申请空间失败,则原有内容也会失去。故使用新的指针变量接收。
  if(ptr!=NULL)
    {
      p=ptr; 
      return 1;
    }
  for (i=0;i<10;i++){
    printf("%d\n",*(p+i));
  } 
  free(p);//->只能释放所有开辟的空间
  p=NULL;
  system("pause");
  return 0;
}

动态开辟若未释放则可能会找出内存泄露,只有free能够释放内存

 

 9.柔性数组

 10.文件操作

 

#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<error.h>
int main(){
  //打开文件
  FILE* pf=fopen("E:\\WordFile\\text.txt","w");
  if(pf==NULL){
    printf("%s\n",strerror(errno));
    return 1;
  }
  //写文件
  for (char i='a';i<='z';i++){
    fputc(i,pf);
  }
  fclose(pf);
  pf=NULL;
  //打开文件
  FILE* ch=fopen("E:\\WordFile\\text.txt","r");
    if(ch==NULL){
    printf("%s\n",strerror(errno));
    return 1;
  }
  //读文件
  char ch1;
  while((ch1=fgetc(ch)!=EOF)){
      printf("%c\n",ch1);
  }
  //关闭文件
  fclose(ch);
  ch=NULL;
  system("pause");
  return 0;
}
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<error.h>
int main(){
  //打开文件
  FILE* pf=fopen("E:\\WordFile\\text.txt","w");
  if(pf==NULL){
    //printf("%s\n",strerror(errno));
    perror("fopen");//打印错误信息
    return 1;
  }
  //写文件
  fputs("hello bit",pf);
  fclose(pf);
  pf=NULL;
  system("pause");
  return 0;
}
/*
printf(),在控制台打印输出信息
fprintf(),直接在文件中打印信息
*/

11.预处理

12.#define 定义宏

#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#define SQUARE(X) X*X  //注意:宏是直接将参数替换到表达式中->所以一般最好在上面加括号 例如 (X)*(X)
int main()
 {
  int x,y;
  x=SQUARE(5);//5*5=25
  y=SQUARE(4+1);//4+1*4+1=9
  printf("x=%d\ny=%d\n",x,y);
  system("pause");
  return 0; 
 };  

 

#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#define SQUARE(X) printf("X=%d\n",X);
int main()
 {
  int x=10;
  int y=20;
  printf("x=%d\ny=%d\n",x,y);
  SQUARE(x);
  SQUARE(y);
  printf("hello ""bit");//->两个双引号会自动和合并为一个双引号
  system("pause");
  return 0; 
 };  

#和##号的使用->在宏使用中可以替代变量名,见下代码,要加双引号

#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#define SQUARE(X) printf(""#X"=%d\n",X);//->#X转化为双引号加变量名
int main()
 {
  int x=10;
  int y=20;
  printf("x=%d\ny=%d\n",x,y);
  SQUARE(x);
  SQUARE(y);
  printf("hello ""bit");//->两个双引号会自动和合并为一个双引号
  system("pause");
  return 0; 
 };  

#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#define CAT(X,Y) X##Y
int main()
 {
  int xy=30;
  int y=20;
  int x=10;
  printf("x=%d\ny=%d\nxy=%d\n",x,y,CAT(x,y));
  system("pause");
  return 0; 
 };  

#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#define MAX(X,Y) ((X)>(Y) ? (X):(Y));
int main()
 {
  int x=5;
  int y=4;
  int m=MAX(x++,y++);//->(x++)>(y++)?x++:y++;
                    //5>4?比较之后x=6,y=5,即m=6,赋值之后 x=7,y++未执行所以不变为5;
  printf("m=%d\nx=%d\ny=%d\n",m,x,y);
  system("pause");
  return 0; 
 };  

宏和函数的对比

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值