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