ALOT学习——小结:多文件编译、static与extern、strlen与sizeof、printf

每周小结

一、Linux系统下的多文件编译

为什么要多文件编译?
在编译的时候,特别是比较大的程序,若不拆分成多个文件,检查代码错误的过程将会是一个痛苦的过程;因此我们可以把一个完整的程序中的每一个函数分离开来,写成.c文件,最后一起编译和链接。

.h文件中一般是声明,包括:变量声明、宏定义、枚举声明、结构体声明、函数声明等。
.h头文件是对该模块(.c文件)接口的声明,接口包括该模块提供给其他模块调用的外部函数以及外部全局变量。其他模块访问这些外部定义的变量和函数都需要在.h文件中冠以extern关键字声明;模块(.c文件)内的函数和全局变量一般需要在.c文件开头冠以static关键字声明。
所以说永远不要在.h文件中定义变量,但可以声明变量
整体用法:

#ifndef AB_H					//如果没有ab.h文件,#define AB_H。如果有,结束定义
#define AB_H					//定义ab.h文件
//定义ab.h需要的头文件
#endif

例如:

#ifndef AB_H
#define AB_H
定义程序所需的一些头文件
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
......
#endif

.c文件的书写
在写每个函数之前要加载头文件,如果是.h文件,就需要写#include”ab.h”。
例如:引用之前的ab.h文件书写aa.c命名的如下文件

#include”ab.h”
int numadd(int a,int b)
{
return a+b;
}

主函数(add.c):

#include”ab.h”
int main(int argc, char const* argv[])
{
int sum;
sum = numadd();
printf("%d",sum);
}

保存退出。
程序编辑完成之后,需要编译链接。
我们可以用gcc编译每个.c文件。如果有三个.c文件add.c、ab.c,编译方法如下:
gcc -c add.c -o add.o //首先分别编译成.o文件
gcc -c ab.c -o ab.o
gcc add.o ab.o -o all //将.o文件编译成一个可执行文件
./all //执行程序

二、static、extern关键字

1.static

(1)针对于声明周期,使其声明的变量存放到静态区,也就是给变量续命;

无static时代码如下(示例):

#include <stdio.h>
void print_out()
{
    int a = 10;
    a++;
    printf("a=%d,", a);
}
int main(int argc, char* argv[])
{
    for (int i = 0; i < 10; i++)
    {
        print_out();
    }
    printf("\n");
    return 0;
}

其运行结果为:

zpr@ubuntu:~/bace$ ./a.out
a=11,a=11,a=11,a=11,a=11,a=11,a=11,a=11,a=11,a=11,

有static时代码如下(示例):

#include <stdio.h>
void print_out()
{
    static int a = 10;
    a++;
    printf("a=%d,", a);
}
int main(int argc, char* argv[])
{
    for (int i = 0; i < 10; i++)
    {
        print_out();
    }
    printf("\n");
    return 0;
}

其运行结果为:

zpr@ubuntu:~/bace$ ./a.out
a=11,a=12,a=13,a=14,a=15,a=16,a=17,a=18,a=19,a=20,

(2)static针对于作用域,其表示限定作用域,在某.c文件中声明的函数,添加后只能适用于当前的.c文件。
无static时代码如下(示例):
1.c文件:

#include <stdio.h>

char a = 'B';
void print()
{
    printf("hello\n");
}

2.c文件:

#include <stdio.h>

void print();

int main(int argc, char const* argv[])
{
    extern char a;
    printf("%c ", a);
    print();
    return 0;
}

其运行结果为:

zpr@ubuntu:~/bace$ gcc -c 1.c -o 1.o
zpr@ubuntu:~/bace$ gcc -c 2.c -o 2.o
zpr@ubuntu:~/bace$ gcc 1.o 2.o -o all
zpr@ubuntu:~/bace$ ./all
B hello

有static时代码如下(示例):
1.c文件:

#include <stdio.h>

char a = 'B';
static void print()
{
    printf("hello\n");
}

2.c文件:

#include <stdio.h>

void print();

int main(int argc, char const* argv[])
{
    extern char a;
    printf("%c ", a);
    print();
    return 0;
}

其运行结果为:

zpr@ubuntu:~/bace$ gcc -c 1.c -o 1.o
zpr@ubuntu:~/bace$ gcc -c 2.c -o 2.o
zpr@ubuntu:~/bace$ gcc 1.o 2.o -o all
/usr/bin/ld: 2.o: in function `main':
2.c:(.text+0x36): undefined reference to `print'
collect2: error: ld returned 1 exit status

2.extern

1、函数的声明extern关键词是可有可无的,因为函数本身不加修饰的话就是extern。但是引用的时候一样需要声明的。

2、全局变量在外部使用声明时,extern关键字是必须的,如果变量没有extern修饰且没有显式的初始化,同样成为变量的定义,因此此时必须加extern,而编译器在此标记存储空间在执行时加载内并初始化为0。而局部变量的声明不能有extern的修饰,且局部变量在运行时才在堆栈部分分配内存。

3、全局变量或函数本质上讲没有区别,函数名是指向函数二进制块开头处的指针。而全局变量是在函数外部声明的变量。函数名也在函数外,因此函数也是全局的。

4、谨记:声明可以多次,定义只能一次。

5、extern int i; //声明,不是定义
int i; //声明,也是定义

三、strlen与sizeof的区别

strlen 是一个函数,它用来计算指定字符串 str 的长度,但不包括结束字符(即 null 字符)。
原型:

size_t strlen(char const* str);

函数用法:计算给定字符串的(unsigned int型)长度,不包括’\0’在内。
因为函数 strlen 的返回结果是 size_t 类型(即无符号整型),而 size_t 类型绝不可能是负的。

关键字 sizeof 是一个单目运算符,而不是一个函数。与函数 strlen 不同,它的参数可以是数组、指针、类型、对象、函数等。
strlen的结果要在运行的时候才能计算出来,是用来计算字符串的长度,不是类型占内存的大小

四、printf("%d,%d,%d,%d",a++ ,++a )的编译问题

1、 printf函数对于括号内的表达式是从右向左执行,如 printf("%d,%d",b++,++b);先执行 ++b,再执行b++;
对于++b的输出,不管它放在printf的哪个位置,调用时使用的都是b的最终值,即4轮自增操作以后的值
而b++则在每一步计算时先把b保存到新寄存器,再把b+1后的结果赋给b

2、对于++a和a++:

++a是先自加,再调用

a++是先调用,再自加
例子:

#include <stdio.h>
int main()
{
    int a=8;
    printf("%d %d %d %d\n",a++,++a,a--,--a);
    printf("%d %d %d %d\n",++a,a++,a--,--a);
    printf("%d %d %d %d\n",++a,a--,a++,--a);
    printf("%d %d %d %d\n",++a,a--,--a,a++);
    return 0;
}
zpr@ubuntu:~/bace$ ./a.out
7 8 7 8
8 6 7 8
8 8 7 8
8 8 8 8

总结

重在坚持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

钟某某人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值