目录
main函数可以有参数吗?
(这个问题从Java中已知,有的)
c
#include <stdio.h>
int main(int argc, char *argv[]) //因为c没有类似STL的功能,因此要用argc变量进行个数传参
{
return 0;
}
发现可以正常编译与运行
c
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("argc: %d\n", argc);
int i = 0;
for(; i < argc; i++)
{
printf("argv[%d]->%s\n", i, argv[i]);
}
return 0;
}
argc为参数个数,argv[]是一个char*类型字符串数组
运行结果如下:
bash
$ ./code
argc: 1
argv[0]->./code
$ ./code a
argc: 2
argv[0]->./code
argv[1]->a
$ ./code a b 3
argc: 4
argv[0]->./code
argv[1]->a
argv[2]->b
argv[3]->3
我们在命令行输入的本质就是字符串
shell程序获取之后,会根据空格拆分出多个字符串,作为参数传入
上面的./code a b 3拆为./code,a,b,3总共4个字符串
看不到这个现象,因为是bash和系统自动完成的
传参的作用
c
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("参数数量错误!使用格式:%s -a|-b\n", argv[0]);
return 1;
}
if(strcmp(argv[1], "-a") == 0)
{
printf("func1\n");
}
else if(strcmp(argv[1], "-b") == 0)
{
printf("func2\n");
}
else
{
printf("defalut func\n");
}
return 0;
}
可参考ls -a等命令
编译后运行
bash
$ ./code
参数数量错误!使用格式:./code -a|-b
$ ./code -a
func1
$ ./code -b
func2
$ ./code a
defalut func
细节:
-
命令行参数至少为1,argc >= 1,argv0一定有元素,指向的就是程序名
-
选项是以空格分隔的字符串,一个字符/数字,也是字符串
-
argv\[\]的本质是一张"表",有argc的元素,
argv[argc]内容一定为NULL(最后一个元素永远为NULL)
因此可以这样写for循环
c
for(; argv[i]; i++)
{
printf("argv[%d]->%s\n", i, argv[i]);
}
有一个现象:
bash
$ ./mycommand
this is a command
$ mycommand
-bash: mycommand: command not found
执行自己的程序时必须使用./调用
-
./为相对路径,让OS找到用户要执行的bin(可执行程序)就在当前路径下 -
Linux系统有类似环境变量的东西,PATH,系统会默认在这里查找程序
-
PATH变量是shell语法自带的
bash
$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/s......k/.local/bin:/home/s......k/bin
(其中`:`为分隔符)
PATH的本质就是一个帮助Linux系统找到程序的变量 (windows同理)
-
如果想要将自己的程序可以不使用
./调用: -
添加到
/usr/bin路径,不推荐:会污染环境变量 -
将自己的程序的路径添加到PATH
-
修改PATH:
bash
$ PATH=/home/s......k/code/2025_10_16/
$ echo $PATH
/home/s......k/code/2025_10_16/
$ ls
-bash: ls: command not found
不能直接覆盖PATH!会导致系统无法正常查找其它指令
(退出账号重新登录即可恢复PATH为初始状态)
正确写法:
bash
$ PATH=$PATH:/home/s......k/code/
这样就能正确添加路径
添加路径后,在系统中全局有效!(类似ls等命令)
- Windows系统也有(很熟悉,笔记就不写了)
环境变量:系统级的变量,变量名和变量内容,往往具有全局属性
使用env命令查看所有的环境变量
bash
$ env
XDG_SESSION_ID=3......1
HOSTNAME=...... # 主机名
TERM=xterm # 终端类型
SHELL=/bin/bash # 当前系统用的shell程序
HISTSIZE=1000 # 记录最近历史命令的数量上限,使用 history 命令查看
SSH_CLIENT=0.0.0.0 3......9 22 # 当前云服务器登录用户的ip地址
SSH_TTY=/dev/pts/2 # 当前用户使用的终端文件
USER=s......k # 用户名 whoami
LD_LIBRARY_PATH=:/home/s......k/.VimForCpp/......
LS_COLORS=......
MAIL=......
PATH=/......bin
PWD=/home/s......k/code/ # 当前路径 pwd
LANG=en_US.UTF-8 # 编码格式
HISTCONTROL=ignoredups
SHLVL=1
HOME=/home/s......k # 家目录
LOGNAME=s......k # 登录用户名
CVS_RSH=ssh
SSH_CONNECTION=0.0.0.0 3......9 0.0.0.0 22
LESSOPEN=||/usr/bin/l.......sh %s
XDG_RUNTIME_DIR=/run/user/1004
_=/usr/bin/env
OLDPWD=/home/s......k/ # 上一次所在的路径,使用 cd - 命令
了解PTAH,HOME,SHELL是什么就行
环境变量与C/C++代码之间的联系
c
#include <stdio.h>
int main(int argc, char* argv[], char* env[])//env就是环境变量
{
int i = 0;
for(; env[i]; ++i)
{
printf("env[%d]: %s\n", i, env[i]);
}
printf("this is a command\n");
return 0;
}
bash
$ ./mycommand
env[0]: XDG_SESSION_ID=3......1
# ......
env[23]: OLDPWD=/home/s......k
this is a command
env[]就是系统的环境变量表
语言中有一个char** environ 一直指向环境变量表
这是获取环境变量的第二种方法
c
#include <stdio.h>
#include <unistd.h>
int main()
{
extern char** environ;
int i = 0;
for(; environ[i]; ++i)
{
printf("environ[%d]->%s\n", i, environ[i]);
}
return 0;
}
上面的两种方法都不常用!
getenv可以直接根据变量名获取变量值,否则为NULL
c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* whoami = getenv("USER");
if(whoami == NULL)
{
printf("no USER!\n");
return 0;
}
else if(strcmp(whoami, "root") == 0)
{
printf("can NOT use root!\n");
}
else
{
printf("you are %s\n", whoami);
}
return 0;
}
这样可以写出一个root用户无法使用的程序
环境变量表存储在bash之中,而bash在内存中,因此重新打开云服务器终端即可恢复环境变量表为初始状态。
因此修改环境变量是内存级的
因为所有用户执行的程序与命令,都是bash的子进程,而子进程是可以访问父进程的数据,因此子进程可以访问到bash修改后的全局变量
c
#include <stdio.h>
#include <unistd.h>
char* argv[100];
char* env[100];
int main()
{
argv[0] = (char*)"ls";
argv[1] = (char*)"-a";
env[0] = (char*)"PATH=AAAA";
pid_t id = fork();
if(id == 0)
{
int i = 0;
for(; argv[i]; ++i)
printf("%s\n", argv[i]);
for(i = 0; env[i]; ++i)
printf("%s\n", env[i]);
}
else
sleep(10000);
}
可以正常打印,说明子进程可以获取父进程的环境变量
我们平时执行的程序,都是bash的子进程,因此这些程序的环境变量都是bash提供!
总结:环境变量由父进程提供!
因此所有进程都会识别到bash的环境变量!
bash的环境变量从何而来?
从Linux系统的配置文件中获取
平时手动在命令行修改的环境变量只改了bash,不会修改配置文件,因此重启bash即可重新获取系统配置文件的环境变量表
从哪个配置文件中获取?
bash
$ cd ~
$ ls -al # 要在家目录中查看
total 100
-rw-r--r-- 1 193 Oct 31 2018 .bash_profile
-rw-r--r-- 1 355 Nov 27 21:01 .bashrc
shell
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/.local/bin:$HOME/bin
export PATH
shell
# .bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=
# User specific aliases and functions
alias vim='/home/s......k/.VimForCpp/nvim'
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/.VimForCpp/......
shell
# /etc/bashrc
# System wide functions and aliases
# Environment stuff goes in /etc/profile
# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.
# are we an interactive shell?
if [ "$PS1" ]; then
......
# vim:......
在启动bash时,先调用.bash_profile,然后调用.bashrc,然后调用/etc/bashrc。
修改文件:
shell
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/.local/bin:$HOME/bin
export PATH
echo "This is a change in .bash_profile!"
重新启动bash:
bash
Welcome to ...... Cloud Elastic Compute Service !
This is a change in .bash_profile!
因为每个用户都有自己的家目录,因此只会修改当前用户的bash
本地变量
bash
$ TEST_ENV=12345
$ env | grep TEST_ENV
$ echo $TEST_ENV
12345
这种在shell中定义的是本地变量,不会保存在环境变量表中
使用export导出至环境变量表
bash
$ export TEST_ENV
$ env
# ...
TEST_ENV=12345
# ...
此时 TEST_ENV 也可以被程序获取
使用unset删除环境变量
bash
$ unset TEST_ENV
$ env
# 没有 TEST_ENV
以上操作都是内存级
本地变量:
-
本地变量无法被子进程继承,不具备全局性,只在bash内部可以访问
-
使用export写入变量表,变为全局变量
-
本地变量有自己的语法
bash
$ cnt=0; while [ $cnt -le 10 ]; do echo $cnt; let cnt++; done
0
1
2
3
4
5
6
7
8
9
10
使用env查看环境变量,使用set查看环境变量和本地变量
如果需要将环境变量写为永久,就写到 ~/.bash_profile 中
bash
$ local_value=100
$ env | grep local_value
$ echo $local_value
100
local_value是本地变量,为什么echo可以获取到该变量?
bash
$ PATH=''
$ echo $PATH
$ ls
-bash: ls: No such file or directory
$ pwd
/home/....../code/
$ top
-bash: top: No such file or directory
$ echo "aa"
aa
明明PATH为空,但是一部分程序能运行,一部分不能运行?
命令与命令之间是不一样的!
-
存在的二进制级别的命令:普通命令
-
内建命令:在shell内部自己定义,bash内部的一次函数调用,不依赖第三方路径
相当于编程语言中语言自带的函数(暂时这样理解!)