数据结构与算法程序员C语言

慕课网-Linux C语言结构体-学习笔记

2017-08-22  本文已影响97人  天涯明月笙

Linux C语言结构体

什么是预处理

.c文件->.i文件->.s文件->.o文件->可执行文件

gcc -o helloworld.i helloworld.c -E
-E表示只让gcc执行预处理。

vim跳到整个文档底部,命令::$

宏是什么

c语言常量分为直接常量和符号常量:
#define 标识符 常量值(没有分号)

hello.c源代码:

#include <stdio.h>
#define R 10

int main()
{
    int a =R;
    printf("a=%d\n");
    printf("hello,world!\n");
    return 0;
}

预处理过之后的代码

# 4 "helloworld.c"
int main()
{
    int a =10;
    printf("a=%d\n");
    printf("hello,world!\n");
    return 0;
}

10是直接当做一个字符串来替换。
宏的本质是在预处理阶段发生的单纯的字符串替换(宏替换);
在预处理阶段,宏不考虑语法;

#include <stdio.h>
#define R 10
#define M int main(

M){
    printf("hello,world!\n");
    return 0;
}

预处理是没有问题的。可以编译执行。

宏函数

源代码:

#include <stdio.h>
#define R 10
#define M int main(
#define N(n) n*10



M){
    int a = R;
    int b =N(a);
    printf("b = %d\n",b);
    printf("a =%d\n",a);
    printf("hello,world!\n");
    return 0;
}

预处理之后:

# 8 "hello.c"
int main(){
    int a = 10;
    int b =a*10;
    printf("b = %d\n",b);
    printf("a =%d\n",a);
    printf("hello,world!\n");
    return 0;
}

宏替换中直接替换的优先级问题。

#include <stdio.h>
#define R 10
#define M int main(
#define N(n) n*10
#define ADD(a,b) a+b
int add(int a,int b){
    return a+b;
}


M){
    int a = R;
    int b =N(a);
    int c =add(a,b);
    int d =ADD(a,b);
    int e = ADD(a,b) * ADD(a,b);

    printf("e = %d\n",e);
    printf("b = %d\n",b);
    printf("a =%d\n",a);
    printf("c =%d\n",c);
    printf("d =%d\n",d);
    printf("hello,world!\n");
    return 0;
}
float d = ADD(10.5,20.0)

宏是不考虑数据类型等的。

条件编译。

typedef是怎么回事

注意typedef如果写在方法体内则只可作用于该作用域内{},#define一直全局。

结构体的声明与定义

#include <stdio.h>
struct weapon{
    char name[20];
    int atk;
    int price;
};

int main()
{
   int a =0;
   float b =0.0;

   struct weapon weapon_1;
   return 0;
}

struct 结构体类型名{}

在函数中调用时 struct 结构体类型名 变量名(前两部分效果类似定义 int 变量 中的int)

结构体的初始化与引用。

struct weapon weapon_1 = {"weapon_name",100,200};
   printf("%s\n,%d\n",weapon_1.name,++weapon_1.price);

结构体元素可以和普通变量一样进行操作。

结构体数组

struct weapon weapon_2[2]={{"weapon_name1",50,100},{"weapon_name2",100,200}};
printf("%s\n,%d\n",weapon_2[0].name,weapon_2[1].atk);

结构体指针

struct weapon *w ;  //定义一个指向weapon的w结构体指针
w=&weapon_1;       //具体指向weapon_1的内存地址
(*w).name
w->name
weapon_1.name           //这3种访问类型都是一样效果
   struct weapon *w;
   w = &weapon_1;
   printf("---------------------------------\n");
   printf("name=%s\n,name=%s\n,name=%s\n",(*w).name,w->name,weapon_1.name);
   return 0;

结构体数组指针。不用取地址符&:数组的名字代表了这个数组的内存首地址,数组括号内的长度代表了数组的单元数,数据类型是int的话就按照int类型(32位系统上是4个字节)乘以单元数的长度,如果数据类型是结构体的话就按照结构体的长度乘以单元的长度。
p++,不是内存位置右移了一个字节,而是右移了一个单元长度的结构体weapon的内存长度。所以就不难理解为什么右移到了第二个结构体实例的首地址上了

   struct weapon *p;
   p = weapon_2; //p->name weapon_2[0].name
   printf("%s\n",p->name);
   printf("---------------------------------\n");
   p++;// weapon_2 +1 weapon_2[1]
   printf("%s\n",p->name);
   return 0;

共用体类型是怎么定义的以及怎么使用的

#include <stdio.h>
struct data{
    int a;
    char b;
    int c;
};

int main()
{
   // union data data_1;
   //data_1.b ='C';
   // data_1.a =10;
    printf("%lu",sizeof(struct data));
    return 0;

}

a的偏移量0;b的偏移量4,自身大小为1。偏移量是大小的整数倍,不会填充空间;c的偏移量为5,c自身大小为4.要补齐为8.然后加上c自身的4。
所以整个占用12.然后再判断这个大小12是不是最宽成员的整数倍。

#include <stdio.h>
union data{
    int a;
    char b;
    int c;
};

int main()
{
    union data data_1;
    data_1.b ='C';
    data_1.a =10;
    printf("%p\n,%p\n,%p\n",&data_1.a,&data_1.b,&data_1.c);
    return 0;

}

共用体地址全部相同。

动态数据结构-静态链表

静态数据结构:

链表:

静态链表;(所有节点都是在程序中定义的,而不是临时开辟的)
【由三个武器信息的节点组成,所以用结构体类型作为节点元素】

#include <stdio.h>

struct weapon{
    int price;
    int atk;
    struct weapon * next;
};

int main()
{
   struct weapon a,b,c,*head;
   a.price =100;
   a.atk = 100;
   b.price =200;
   b.atk =200;
   c.price =300;
   c.atk =300;
   head = &a;
   a.next =&b;
   b.next =&c;
   c.next = NULL;

   struct weapon *p;
   p =head;
   while(p!=NULL){
    printf("%d,%d\n",p->atk,p->price);
    p=p->next;

   }
}

动态链表

程序执行过程中从无到有的建立起一个链表,也就是说需要一个一个的开辟新节点,输入新节点的数据,然后建立起前后相连的关系。
建立武器信息的单向动态链表:

#include <stdio.h>
#include <malloc.h>
struct weapon{
  int price;
  int atk;
  struct weapon * next;
};
//【需要一个创建链表的函数,返回值是链表的头指针】
struct weapon * create(){
   struct weapon *head;
   struct weapon *p1,*p2;//3个指针都用来指向struct weapon类型数据,p1,p2分别指向当前新创建和上一个。
   int n=0;//记录当前节点个数
   //malloc分配内存块的函数,sizeof判断数据类型长度符
   p1=p2=(struct weapon*)malloc(sizeof(struct weapon));
   scanf("%d,%d",&p1->price,&p1->atk);
   head = NULL;//一开始链表不存在,置空
   while(p1->price!=0){//约定price为0时停止输入
     n++;
     if(n==1) head=p1;
     else p2->next=p1;

     p2=p1;//保留p1当前所指向的的地址

     //需要开辟一个新的动态存储区,把这个的地址载给p1
     p1=(struct weapon*)malloc(sizeof(struct weapon));
     scanf("%d,%d",&p1->price,&p1->atk);//开辟后输入数据
}
p2->next=NULL;
return (head);
}//p1,p2一个用来指向链表新创立的节点,一个用来指向下一个节点
int main()
{
   struct weapon *p;
   p=create();//p成为链表的头指针
   printf("%d,%d",p->price,p->atk);//打印第一个节点的信息
   return 0;
}

C语言中的位运算符:按位与、按位或、按位异或、左移和右移

按位与

六种位运算符

#include <stdio.h>

int main()
{
   // & | ^ ~ << >>

   int a =4;//0100
   int b =7;//0111

  int c =a&b;//0100

   printf("%d",c);
   return 0;
}

按位与的应用

#include <stdio.h>

int main()
{
   // & | ^ ~ << >>

   int a =4;//0100
   int b =7;//0111

   int c =a&1;//0100

   int d =b&1;//0100
   printf("%d\n",c);
   printf("%d\n",d);
   return 0;
}

输出为0,1.

按位或运算。

#include <stdio.h>

int main()
{
   // & | ^ ~ << >>

   int a =9;//1001
   int b =5;//0101

   int c =a|b;//1101

   printf("%d\n",c);
   return 0;
}

输出为1101:13

按位或的作用:
设定数据的指定位,与255(0xFF)做或运算;

b = b| 0xFF,能设定数据b的指定二进制数后8位置为1
即b的十进制等于255

按位异或

将参与运算的两个数据按对应的二进制数逐位进行逻辑异或运算

按位取反

~1000 = 0111

左移:高速乘以2;右移:高速除以2

左移:将数据对应的二进制值逐位左移若干位;高位丢弃,低位补零;乘以2的n次方
右移:将数据对应的二进制值逐位右移若干位:低位丢弃,高位补0或1(根据符号位判断,就是正数数补0,负数补1);除以2的n次方
高位丢弃,低位补零

递归调用

递归调用有时候会牺牲效率

#include <stdio.h>
int func(int a)
{
    int r =0;
    if(a<0){
    printf("error");
}else if(a==0 || a==1){
    return 1;
}else{
    r =a *func(a-1);
    return r;
}

}

int main()
{
   int a =0;
   printf("please input the num:");
   scanf("%d",&a);
   int r = func(a);
   printf("the result is %d\n",r);
   return 0;
}

递归的工作原理。

  • 递归:大规模——化简——>小规模,直到问题可求。

总结

上一篇 下一篇

猜你喜欢

热点阅读