文章目录
- 1,各种类型所占字节数
- 2,main函数是可以传入参数的
- 3,C语言中extern的用法
- 4,gettop()函数
- 5,C/C++中枚举类型enum使用
1,各种类型所占字节数
类型 | 16位 | 32位 | 64位 |
---|---|---|---|
char | 1 | 1 | 1 |
short int | 2 | 2 | 2 |
int | 2 | 4 | 4 |
unsigned int | 2 | 4 | 4 |
float | 4 | 4 | 4 |
double | 8 | 8 | 8 |
long | 4 | 4 | 8 |
long long | 8 | 8 | 8 |
unsigned long | 4 | 4 | 8 |
2,main函数是可以传入参数的
首先说明的是,可能有些人认为main函数是不可传入参数的,但是实际上这是错误的。main函数可以从命令行获取参数,从而提高代码的复用性。
什么时候使用带参数的主函数?
我们需要和程序进行交互。你知道,在程序运行过程中,可以通过scanf函数,输入数组、字符、字符串给程序处理。那么能不能在程序启动的时候(),就携带参数给他,而不是运行过程中敲入东西给程序。这时候需要用用到带参数(int argc, char argv[])的main函数。
为main函数传参时,可选的main函数原形为: int main(int argc,char*argv[],char*envp[])
①、第一个参数argc表示的是传入参数的个数
②、第二个参数char argv[],是字符串数组,用来存放指向的字符串参数的指针数组,每一个元素指向一个参数。各成员含义如下:
argv[0]:指向程序运行的全路径名
argv[1]:指向执行程序名后的第一个字符串 ,表示真正传入的第一个参数
argv[2]:指向执行程序名后的第二个字符串 ,表示传入的第二个参数
……
argv[n]:指向执行程序名后的第n个字符串 ,表示传入的第n个参数
规定:argv[argc]为NULL ,表示参数的结尾。
③、第三个参数char* envp[],也是一个字符串数组,主要是保存这用户环境中的变量字符串,以NULL结束。
3,C语言中extern的用法
-
extern修饰变量的声明。
举例来说,如果文件a.c需要引用b.c中变量int v,就可以在a.c中声明extern int v,然后就可以引用变量v。能够被其他模块以extern修饰符引用到的变量通常是全局变量。还有很重要的一点是,extern int v可以放在a.c中的任何地方,比如你可以在a.c中的函数fun定义的开头处声明extern int v,然后就可以引用到变量v了,只不过这样只能在函数fun作用域中引用v罢了,这还是变量作用域的问题。对于这一点来说,很多人使用的时候都心存顾虑。好像extern声明只能用于文件作用域似的。 -
extern修饰函数声明。从本质上来讲,变量和函数没有区别。函数名是指向函数二进制块开头处的指针。如果文件a.c需要引用b.c中的函数,比如在b.c中原型是int fun(int mu),那么就可以在a.c中声明extern int fun(int mu),然后就能使用fun来做任何事情。就像变量的声明一样,extern int fun(int mu)可以放在a.c中任何地方,而不一定非要放在a.c的文件作用域的范围中。对其他模块中函数的引用,最常用的方法是包含这些函数声明的头文件。
使用extern和包含头文件来引用函数有什么区别呢?extern的引用方式比包含头文件要简洁得多!extern的使用方法是直接了当的,想引用哪个函数就用extern声明哪个函数。这大概是KISS原则的一种体现吧!这样做的一个明显的好处是,会加速程序的编译(确切的说是预处理)的过程,节省时间。在大型C程序编译过程中,这种差异是非常明显的。 -
此外,extern修饰符可用于指示C或者C++函数的调用规范。
比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。主要原因是C++和C程序编译完成后在目标代码中命名规则不同。
- 举个简单的例子:
用C语言编写程序的时候,我们经常会遇到这样一种情况:希望在头文件中定义一个全局变量,然后包含到两个不同的c文件中,希望这个全局变量能在两个文件中共用。
举例说明:项目文件夹project下有main.c、common.c和common.h三个文件,其中
common.h文件分别#include在main.c和common.c文件中。现在希望声明一个字符型变量key,在main.c和common.c中公用。
有人想,既然是想两个文件都用,那就在common.h中声明一个unsigned char key,然后由于包含关系,在main.c和common.c中都是可见的,所以就能共用了。
这种想法其实是很多初学者都会想到的,想起来确实有道理,但是实际写出来,我们发现编译的时候编译器提示出错,一般提示大概都类似于:Error: L6200E: Symbol key multiply defined (by common.o and main.o). 也就是说编译器认为我们重复定义了key这个变量。这是因为#include命令就是原封不同的把头文件中的内容搬到#include的位置,所以相当于main.c和common.c中都执行了一次unsigned char key,而C语言中全局变量是项目内(或者叫工程内)可见的,这样就造成了一个项目中两个变量key,编译器就认为是重复定义。
正确的解决办法:使用extern关键字来声明变量为外部变量。具体说就是在其中一个c文件中定义一个全局变量key,然后在另一个要使用key这个变量的c文件中使用extern关键字声明一次,说明这个变量为外部变量,是在其他的c文件中定义的全局变量。请注意我这里的用词:定义和声明。例如在main.c文件中定义变量key,在common.c文件中声明key变量为外部变量,这样这两个文件中就能共享这个变量key了。
原创作者;https://blog.csdn.net/gao1440156051/article/details/48035911
4,gettop()函数
int getopt(int argc, char * const argv[], const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt;
getopt 参数说明:
argc:通常由 main 函数直接传入,表示参数的数量
argv:通常也由 main 函数直接传入,表示参数的字符串变量数组
optstring:一个包含正确的参数选项字符串,用于参数的解析。例如 “abc:”,其中 -a,-b 就表示两个普通选项,-c 表示一个必须有参数的选项(此时参数和-c之间的空格可有可无),因为它后面有一个冒号,"abc::"则表示-c之后可跟参数也可以不用跟参数(此时 选项 -c 后面跟参数的时候,一定不能有空格)
外部变量说明:
optarg:如果某个选项有参数,这包含当前选项的参数字符串
optind:argv 的当前索引值
opterr:正常运行状态下为 0。非零时表示存在无效选项或者缺少选项参数,并输出其错误信息
optopt:当发现无效选项字符时,即 getopt() 方法返回 ? 字符,optopt 中包含的就是发现的无效选项字符;
用一个例子说明:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int o;
const char *optstring = "abc:"; // 有三个选项-abc,其中c选项后有冒号,所以后面必须有参数
while ((o = getopt(argc, argv, optstring)) != -1) {
switch (o) {
case 'a':
printf("opt is a, oprarg is: %s\n", optarg);
break;
case 'b':
printf("opt is b, oprarg is: %s\n", optarg);
break;
case 'c':
printf("opt is c, oprarg is: %s\n", optarg);
break;
case '?':
printf("error optopt: %c\n", optopt);
printf("error opterr: %d\n", opterr);
break;
}
}
return 0;
}
分析:
命令 gcc OptDemo.c -o OptDemo 是使用 gcc 把 OptDemo.c 编译成可执行程序,命名为 OptDemo
第一次运行 ./OptDemo -a -b -c afei 正常执行和输出
第二次运行 ./OptDemo -abc 由于选项 c 后没有输入参数,于是报错
第三次运行 ./OptDemo -d 由于选项 d 不是我们在 optstring 中预定义的选项,于是报错
原文链接:https://blog.csdn.net/afei__/article/details/81261879
5,C/C++中枚举类型enum使用
1. 说明:
枚举enum的出现,主要是为了解决一些特定属性的赋值,变量取值仅在一定有限范围内的问题。例如一年只有十二个月取值,一个星期只有七天情况,人的性别只有男女两种等。这些属性如果简简单单用int类型变量定义就有失妥当,能取的值远远超出可取值范围。所以我们希望给这些属性变量,定义一个有限取值范围。
枚举即将变量的值一一列举出来,变量只限于列举出来的值的范围内取值。
2. 定义
语法结构:
enum [枚举名] {e1[=Value1], e2[=Value2] ,… …};
e1、e2… …:称为枚举常量,枚举成员,也称为枚举子。
Value1,Value2… …:称为枚举子值,即枚举值,可忽略不写,默认从0依次赋值。
例如:
enum color {red,green,blue}; //枚举值分别为0,1,2.
定义枚举类型变量:
[enum] 枚举名 枚举变量名 [=初始化值];
例如:
color paint = red;
enum color paint = red;
enum color {red=1 , green =5, blue=10} paint;
3. 枚举语法
①.枚举成员不是变量,而是常数,和const定义常变量一样,所以不能对枚举元素进行赋值。
②.枚举成员作为常量,定义的时候存储的值按列举顺序依次默认为0,1,2……。当然,声明时候可以修改其存储值,即修改枚举值,但不可以为负数,如-1,-2等,且枚举值为整数。
例如:
enum color {red, green=10,blue}; //依次为0,10,11
这种情况下,red枚举值依旧默认为0,green则为10,而blue没有赋值,则随上个枚举值递增下去,所以为11。
枚举值在未特定赋值外,后续枚举成员默认都是依上个成员的枚举值依次递增的。
③. 枚举成员不是简单字符串常量,使用的时候无需添加单、双引号。
④.枚举成员不可以重复,但是枚举值可以重复。重复枚举值的枚举成员表明它们具有共同性质,所以放在一起。
例如:
enum weeks {mon=1,tue=1,wed=1,thu=1,fri=1,sat=2,sun=2};
一周周一到周五是工作日,我们希望它们具有共性和相同的枚举值。而周末休息,我们希望它两有另外一个枚举值。
⑤.一个整数不能直接赋给一个枚举变量,必须强制进行类型转换才能赋值。
例如:
enum weeks day;
day =(weeks)2;
⑥.枚举值可以用在if-else或者switch-case判断中。
例如:
if(day != mon)
{
printf("今天是工作日\n");
}
⑦.**编译平台输出枚举类型变量,输出的不是枚举常量名称,而是枚举值。**就像const int n=1输出的并不是’n’这个字符,而是1这个值。
例如:
enum weeks day = mon; //定义枚举weeks类型变量并初始化
day = (weeks)2;
cout<<day<<endl; //输出结果为2,并不是"sat"字符串常量
4. 枚举应用程序
当输入今天星期几(1-7),我们希望判断今天是否上班(公司规定周一到周五工作,周末休息)。
#include<stdio.h>
int main( )
{
enum weekday {sun=1,mon,tue,wed,thu,fri,sat} day; //从1开始
int k;
printf("请输入今天星期几(1--7):");
scanf("%d",&k);
day=(enum weekday)k;
switch(day)
{
case mon:
case tue:
case wed:
case thu:
case fri: printf("今天上班\n"); break;
case sun:
case sat: printf("今天休息\n"); break;
default: printf("输入有误\n"); break;
}
return 0;
}
原文链接:https://blog.csdn.net/fx677588/article/details/52679803