嵌入式第十四天

本文深入解析GCC编译流程,包括预处理、编译、汇编和链接等阶段,并通过实例演示多文件编译及调试技巧。同时,详细介绍Makefile的编写方法,涵盖目标依赖、规则简化及变量定义等内容,帮助读者掌握项目自动化构建。
摘要由CSDN通过智能技术生成

shell 
复习:
gcc 
gcc a.c -o a

预处理:去掉# 
gcc -E a.c -o a.i 

编译:
gcc -S a.c -o a.s 
汇编:
gcc -c a.c -o a.o 

链接:
gcc a.c -o a 

一、程序编译问题
1.两类:
    hello.c:7:2: 错误: expected ‘;’ before ‘return’  //缺少分号
    hello.c:(.text+0x19): undefined reference to `prin' //链接
    collect2: ld 返回 1

    hello.c:4:2: 警告: 隐式声明与内建函数‘printf’不兼容 [默认启用]  

2.gcc hello.c -o hello -Wall   //-Wall 显示所有警告

二、多文件编译
    //main.c 
    #include<stdio.h>
    int main()
    {
        fun();
        puts("i am main....");    
    }

    //fun.c 
    #include<stdio.h>
    void fun()
    {
        puts("i am fun....");
    }

    gcc main.c fun.c 
    ./a.out


 练习:从键盘输入一个正数 输出此数的位数  如:235 3  1234  4
 //main.c 
 #include<stdio.h>
int main()
    {
        int n;
        puts("input :");
        scanf("%d",&n);
        printf("%d\n",judge(n));
    }
        
        
//judge.c 
#include<stdio.h>

    int judge(int a)
    {
        int count=0;
        while(a!=0)
        {
            a/=10;
            count++;
        }

        return count;
    }
gcc main.c judge.c  -o judge
./judge


三、GDB调试
 gcc hello.c -o hello -g //-g 会将调试信息写入可执行文件 程序会变大
 list  //默认显示前10行
 (gdb) break 4  //表示在第4行设置断点
 run //在断点处停下来  可以查看变量的值
 print i //查看变量的值
 c //继续运行 如果碰到断点会停下来
 n //一次执行一行
 q //退出
 
 跟我一起写Makefile
 
 
四、项目管理器makefile
1.
    主要多文件编译
    Makefile里面主要是源代码的编译规则 通过make命令 来执行makefile 
    make执行时 需要一个makefile 

2.makefile 名称:makefile Makefile MAKEFILE
 (1)编写Makefile
     //vi Makefile
     ///
    hello:
        gcc main.c fun.c -o hello 
    
    执行:make 

    make 是命令 当执行这个命令 会自动找Makefile 
    make: “hello”是最新的。//执行make时 会检查源文件是否有更新 如果没有更新 不重新编译

(2)clean
    /
    hello:
        gcc main.c fun.c -o hello 
    clean:
        rm hello 
    
    make clean   //make命令可以执行某一个目标 如clean  

练习: 
    jud
        gcc main.c judge.c -o judge    
    clean:    
        rm judge

(3)//如果一个目录依赖于另一个目标 则另一个目标也会被执行
    hello:main.c fun.c   //hello目标依赖于main.c fun.c 
        gcc main.c fun.c -o hello 
    clean:
        rm hello 
    rebuild:clean hello   //先执行clean 再执行hello  

(4)为了提高编译效率 通常会先将.c文件生成.o目标文件
然后如果某个源文件修改 就重新相应的.o文件 其他的没有修改的.c文件则不会重新编译
hello:main.o fun.o 
    gcc  main.o fun.o -o hello 
main.o:main.c 
    gcc -c main.c vi 
fun.o:fun.c 
    gcc -c fun.c         
    
clean:
    rm hello 
rebuild:clean hello  
//如果main.c 修改 重新生成main.o fun.c 不会重新生成    
    
(5)简化:
    Makefile文件中可以使用一些预设变量
    $@是完整的目标名称
    $^ 所有依赖
    $< 第一个依赖文件
    预设变量不可以放在":"行,在这一行依赖关系最好写上。
    hello:main.o fun.o i
        gcc  $^ -o $@ 
    main.o:main.c 
        gcc -c $< 
    fun.o:fun.c 
        gcc -c $<
    继续简化:
    .o:.c
        gcc -c $<
    //     
    hello:main.o fun.o 
        gcc  $^ -o $@ 
    .o:.c
        gcc -c $<    
        
    clean:
        rm hello 
    rebuild:clean hello  
    /        
(6)再简化
 在Makefile中可以定义变量 定义变量好处:方便修改
 //     
    EXEC = hello 
    CC = gcc 
    OBJ = main.o fun.o 
    $(EXEC):$(OBJ)
            $(CC) $^ -o $@
    .o:.c
            $(CC) -c $<    
    clean:
        rm $(OBJ)
        rm $(EXEC)
    rebuild:clean $(EXEC)    
/        
跟我一起写Makefile

五、指针
1.定义指针
    int * p;

    int a=90 ;
    p = &a;

    *p=100;
    a=100;

    int b;
    p=&b;

    char* q;
    float *f;
    ..
2.指针指向数组
    int a[5];
    数组名:数组首地址==&a[0]
    int *p;
    p=a;
    for(i=0;i<5;i++)
    {
        *(p+i) 
    }

六、数组指针:本质是指针  指向二维数组的指针
    int a[2][3]={{10,20,30},{40,50,60}}
1.如何定义数组指针指向二维数组
    int (*p)[3];//定义一个指针p 指向列数为3的二维数组 数组中每个元素类型为int

    数组指针定义必须明确要指向的二维数组的列数

2.使用、
    #include<stdio.h>
    int main()
    {
        int i,j;
        int a[2][3]={{10,20,30},{40,50,60}};
        int (*p)[3];
        p = a;

        for(i=0;i<2;i++)
        {
            for(j=0;j<3;j++)
            {
                printf("%d ",p[i][j]);//注意此处p[i][j]=(*(p+i)[j])
            }
            putchar('\n');
        }
        return 0;
    }    

练习:已知二维数组
int a[3][4]={{7,10,-2,3},{4,30,6,-15},{0,5,27,-7}};
利用数组指针将数组中各个元素相加求和
    #include<stdio.h>
    void get_sum(int (*p)[4],int row)//int(*)[4]
    {
        int i,j,sum=0;
        for(i=0;i<row;i++)
            {
                for(j=0;j<4;j++)
                {
                    sum = sum+p[i][j];
                }
            }
            printf("%d\n",sum);
    }
    int main()
    {
        int a[3][4]={{7,10,-2,3},{4,30,6,-15},{0,5,27,-7}};
        get_sum(a,3);//int (*)[4]
        return 0;
    }    

七、指针数组:本质是数组 由指针组成的数组
    int (*p)[3]
    int * p[3] |int*|int*|int*|
    char *p[3]  |char*|char*|char*|

    char *a[3]={"zhao","qian","sun"};
    //a[0]="zhao"
    //a[1]="qian"
    for(i=0;i<3;i++)
    {
        printf("%s\n",a[i]);
    }

八、冒泡排序
char *p[5]={"yang","li","liu","wang","zhang"};

1.冒泡 
冒泡排序
实现过程:从小到大 
(1)比较数据中的前两个数 将大数放后面 较小数放前面  然后比较第二个数和
第三个数
(2)依次类推
(3)如果n个数据排序 需要排n-1趟

#include<stdio.h>
#include<string.h>
int main()
{
    char *p[5]={"yang","li","liu","wang","zhang"};
    int i,j;
    char *t;s
    for(i=0;i<4;i++)
    {
        for(j=0;j<4-i;j++)
        {
            if(strcmp(p[j],p[j+1])>0)
            {
                
                t = p[j];
                p[j] = p[j+1];
                p[j+1] = t;
            }
        }
    }
    
    for(i=0;i<5;i++)
    {
        puts(p[i]);
    }
    return 0;
}    

九、函数 
1.
    int fun(int ,int );
    int main()
    {
        int x = fun(x,y);
    }
    int fun(int a,int b)
    {
        语句;
        return 90;
    }

    练习2:
    #include<stdio.h>
    void fun(char ch,int col,int row)
    {
        int i,j;
        for(i=0;i<row;i++)
        {
            for(j=0;j<col;j++)
            {
                putchar(ch);
            }
            putchar('\n');
        }
    }
    int main()
    {
        fun('a',5,3);
        return 0;

    }

2.交换函数        
    #include<stdio.h>
    void swap(int *pa,int *pb)
        {
            int tmp;
            tmp = *pa;
            *pa = *pb;
            *pb = tmp;
        }
        
        void sort(int *p,int n)
        {
            int i,j;
            for(i=0;i<n-1;i++)
            {
                for(j=0;j<n-1-i;j++)
                {
                    if(p[j]>p[j+1])
                    {
                        swap(&p[j],&p[j+1]);
                    }
                }
            }
        }
        
        void out_put(int *p,int  n)
        {
            int i;
            for(i=0;i<n;i++)
            {
                printf("%d ",p[i]);
            }
        }
        int main()
        {
            int a[]={6,3,8,0,1,34,9,90};    
            sort(a,sizeof(a)/sizeof(int));    
            out_put(a,sizeof(a)/sizeof(int));
        }    

    作业1:函数练习题4,5
     int my_strcmp( char *s1, const char *s2);
     #include<stdio.h>
    int fun(char *p,char *q)
    {
        for(;!((*p=='\0')&&(*q=='\0'));p++,q++)
        {
            if(*p==*q)
            {
                continue;
            }
            else if(*p>*q)
            {
                return 1;
                break;
            }
            else
            {
                return -1;
                break;
            }
        }
        return 0;
    }
    int main()
    {
        char a[50];
        char b[50];
        puts("inpuy two string:");
        scanf("%s\n",a);
        scanf("%s",b);
         int x=fun (a,b);
         printf("%d",x);
    }
        

    练习5:
    #include<stdio.h>

    int is_within(char c,char *str)
    {
        while(1)
        {
            if(*str==c)
            {
                return 1;
            }
            else
            {
                str++;
                if(*str=='\0')
                    return 0;
            }
        }
    }

    int main()
    {
        char str[30];
        char c;
        int x;

        puts("Please input the char:");
        c=getchar();
        getchar();
        puts("Please input the str:");
        gets(str);
        x=is_within(c,str);
        printf("%d\n",x);
        return 0;
    }
    
    作业2:指针练习题第5题    
    1 3 5 7 9
    2 4 6 8 10 12 14 16 
    
    1 2 3 4 5 6 7 8 9 10 12 14 

    指针版本:
    #include<stdio.h>
    void sort(int *p1,int *p2)
    {
        int i=0,j=0;
        while(i<10&&j<10)
        {
            if(*p1<*p2)
            {
                printf("%d ",*p1);
                p1++;
                i++;
            }
            else 
            {
                printf("%d ",*p2);
                p2++;
                j++;
            }
        }
        
        if(i<j)
        {
            while(i<10)
            {
                printf("%d ",*p1);
                p1++;
                i++;
            }
        }
        else 
        {
            while(j<10)
            {
                printf("%d ",*p2);
                p2++;
                j++;
            }
        }
    }
    int main()
    {
        int a[10]={1,3,5,7,9,11,13,15,17,19};
        int b[10]={2,4,6,8,10,11,14,16,18,20,};
        
        sort(a,b);
    }


    
    
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值