默认计划
491人加入学习
(0人评价)
【研发工程师】C语言程序设计
价格 ¥ 970.00
该课程属于 名企研发核心能力课 请加入后再学习

main函数的参数讲解 

int main(int argc, char* argv[], int** env)

#include <stdio.h>

int main(int argc, char* argv[], char** env) {
    printf("%d\n", argc);
    for (int i = 0; i < argc; i++) {
        printf("argv[%d] = %s\n", i, argv[i]);
    }
    for (int i = 0; env[i]; i++) {
        printf("env[%d] = %s\n", i, env[i]);
    }
    return 0;
}

以下两种方式可以将空格作为字符串传入

./a.out "hello world"

./a.out hello\ world

环境变量字符串数组env[]最后的是NULL表示结尾

----------------------------------------------

工程项目开发:

函数声明和定义

报错:

函数未声明(编译阶段:检查语法、语义)

"xxx" was not declared in this scope

 

 函数未定义(链接阶段:组装拼接)

undefined reference(引用) to "xxx"

error:ld returned 1 exit status(链接阶段错误)

 

函数重定义(链接阶段):链接的两个.o中某个函数有两个定义。

multiple definition of "xxx"

error:ld returned 1 exit status(链接阶段错误)

 

区分报错的时期不同

 

文件main.cpp

#include <stdio.h>
void funcB(int);
void funcA(int n) {
    if (n == 0) return ;
    printf("funcB : %d\n", n);
    funcB(n - 1);
    return ;
}

int main() {
    funcA(5);
    return 0;
}

文件unite.cpp

#include <stdio.h>
void funcA(int);
void funcB(int n) {
    if (n == 0) return ;
    printf("funcB : %d\n", n);
    funcA(n - 1);
    return ;
}

 

g++ -c main.cpp 生成main.o

g++ -c unite.cpp 生成unite.o

g++ main.o unite.o 生成a.out

------------------------------------------------

头文件(xxx.h)与源文件(xxx.c cc cpp)

头文件放声明;

源文件放定义。

 

自己写的头文件要用 #include "xxx.h"

 

<>的头文件,编译器从系统路径下查找头文件。

""的头文件,编译器从当前路径下查找头文件。

 

头文件中不许写函数定义,否则容易造成重定义,以及头文件包含需要顺序

 

条件式编译:

#ifndef _xxx_
#define _xxx_
#endif

//如果没定义_xxx_宏
//则定义_xxx_宏

_xxx_最好和头文件一个名字

 

.o文件可以通过ld命令查看

---------------------------------------------

如果把函数定义写到头文件:

文件main.cpp

#include <stdio.h>
#include "head_c.h"
#include "head_ab.h"
//#include "head_d.h" 

int main() {
    funcA(5);
    funcC(2, 3);
    //funcD(3, 4);
    return 0;
}

文件head_ab.h

#ifndef _HEAD_AB_H
#define _HEAD_AB_H

void funcA(int);
void funcB(int);

void funcA(int n) {
    if (n == 0) return ;
    printf("funcA : %d\n", n);
    funcB(n - 1);
    return ;
}

void funcB(int n) {
    if (n == 0) return ;
    printf("funcB : %d\n", n);
    funcA(n - 1);
    return ;
}

#endif

文件head_c.h

#ifndef _HEAD_C_H
#define _HEAD_C_H

#include "head_ab.h"
void funcC(int a, int b) {
	printf("FuncC : %d + %d = %d\n", a, b, a + b);
	funcA(a);
	return ;
}
#endif

以上虽然不会报错,但是如果再添加其他.cc文件

文件head_d.h

#ifndef _HEAD_D_H
#define _HEAD_D_H
void funcD(int, int);
#endif

文件head_d.cc

#include <stdio.h>
#include "head_ab.h" 

void funcD(int a, int b) {
	printf("funcD : %d + %d = %d\n", a, b, a + b);
	funcA(a);
	return ;
}

则在head_d.cc中又包含了head_ab.h,造成了函数的重定义,所以函数定义不能放在头文件。

------------------------------------------------

Linux工程项目规范:

根目录:

文件夹include放全部的.h

文件夹src全部放.cc

文件夹bin放exe

文件夹lib放.a静态链接库

main.cpp放在外面

Makefile

 

头文件:

funcAB.h

#ifndef _FUNC_AB_H
#define _FUNC_AB_H
void funcA(int);
void funcB(int);
#endif

funcC.h

#ifndef _HEAD_C_H
#define _HEAD_C_H
void funcC(int, int);
#endif

funcD.h

#ifndef _FUNC_D_H
#define _FUNC_D_H
void funcD(int, int);
#endif

 

源文件:

文件main.cpp

#include <cstdio>
#include <funcAB.h>
#include <funcC.h>
#include <funcD.h>

int main() {
    funcA(5);
    funcC(2, 3);
    funcD(3, 4);
    return 0;
}

./src/funcAB.cc

#include <funcAB.h>
#include <cstdio>
void funcA(int n) {
    if (n == 0) return ;
    printf("funcA : %d\n", n);
    funcB(n - 1);
    return ;
}

void funcB(int n) {
    if (n == 0) return ;
    printf("funcB : %d\n", n);
    funcA(n - 1);
    return ;
}

./src/funcC.cc

#include <funcAB.h>
#include <cstdio>
void funcC(int a, int b) {
	printf("FuncC : %d + %d = %d\n", a, b, a + b);
	funcA(a);
	return ;
}

./src/funcD.cc

#include <funcAB.h>
#include <cstdio>
void funcD(int a, int b) {
	printf("funcD : %d + %d = %d\n", a, b, a + b);
	funcB(b);
	return ;
}

如果想将自己的头文件引用" "变成< >,

则改完以后自己在gcc 后加参数-I./include

 

Makefile工具:方便多文件链编

.PHONY: clean
all: main.o ./src/funcAB.o ./src/funcC.o ./src/funcD.o libtest.a
	g++ -I./include -L./lib main.o -ltest -o ./bin/test.exe
./src/funcAB.o: ./include/funcAB.h ./src/funcAB.cc
	g++ -I./include -c ./src/funcAB.cc -o ./src/funcAB.o
./src/funcC.o: ./include/funcC.h ./src/funcC.cc
	g++ -I./include -c ./src/funcC.cc -o ./src/funcC.o
./src/funcD.o: ./include/funcD.h ./src/funcD.cc
	g++ -I./include -c ./src/funcD.cc -o ./src/funcD.o
main.o: main.cpp ./include/*.h
	g++ -I./include -c main.cpp
libtest.a: ./src/funcAB.o ./src/funcC.o ./src/funcD.o
	ar -r ./lib/libtest.a src/*.o
clean:
	rm ./bin/test.exe main.o ./src/*.o ./lib/libtest.a

加.PHONY: clean是防止:如果当前路径下有文件名字为clean,则不影响。功能是创建一个虚拟空间清理。

 

------------------------------------------------

链接库:

不能直接发同时src和include,因为首先对方要自己写makefile编译链接,其次没有保密性。

 

头文件可以发,源文件要变成链接库。

动态链接库:压缩的很小,开放权限共享

静态链接库:比较大,一对一的copy

 

自己搜:不同系统下如何生成静态链接库

 

以下为linux环境:

ar -r libxxx.a src/*.o  生成了静态链接库
lib是前缀, .a是后缀 ,中间xxx是名字,后续指定库时候的参数是-lxxx

然后:

g++ -I./include -c main.cpp 

生成main.o

然后:

g++ -I./include -L./lib main.o -lxxx
注意main.o在前,-lxxx在后

即可调用库生成a.out

 

[展开全文]

授课教师

C++算法工程师

课程特色

视频(31)