C语言知识扫盲

1,各种类型所占字节数

类型16位32位64位
char111
short int222
int244
unsigned int244
float444
double888
long448
long long888
unsigned long448

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的用法

  1. 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声明只能用于文件作用域似的。

  2. 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程序编译过程中,这种差异是非常明显的。

  3. 此外,extern修饰符可用于指示C或者C++函数的调用规范。

比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。主要原因是C++和C程序编译完成后在目标代码中命名规则不同。

  1. 举个简单的例子:
    用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

6,C语言中的access()函数

1,access()函数用来判断用户是否具有访问某个文件的权限(或判断某个文件是否存在)

2,头文件#include<unistd.h>

3,参数和返回值

  int access(const char *pathname,int mode)

参数:
pathname:表示要测试的文件的路径
mode:表示测试的模式可能的值有:

R_OK:是否具有读权限
W_OK:是否具有可写权限
X_OK:是否具有可执行权限
F_OK:文件是否存在

返回值:若测试成功则返回0,否则返回-1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值