C语言词法元素

系列文章目录

  1. C语言综述1
  2. C语言字符集2
  3. C语言词法元素3
  4. C语言表达式4
  5. C语言语句5
  6. C语言声明6
  7. C语言预处理指令7
  8. C语言头文件8


前言

蓝色问号代表个人理解   绿色代表来源   红色问号代表尚有疑问

为什么要读标准?因为全面、权威,所有答案都在标准里面!
哪些人适合浏览本系列文章?不清楚C语言程序的组成,以及每个组成部分的详细内容
持续更新,码字不易,求点赞收藏


前言

为什么要读标准?因为全面、权威,所有答案都在标准里面!
哪些人适合浏览本系列文章?不清楚C语言程序的组成,以及每个组成部分的详细内容
持续更新,码字不易,求点赞收藏

1、概述

  1. token,国标翻译为单词,但是感觉不准确
  2. 翻译3~6阶段所有词法元素为预处理token,7、8阶段已转换成了token
  3. 转换为token的每个预处理token应具有token的词汇形式
  4. 字符与最后一个类别的预处理单元(不属于上述范围内的任一非白空类符)匹配,行为未定义
  5. 预处理单元可以被白空类单元分隔(注释或白空类符或两者都有)
  6. 若直至某个给定字符为止的输入流字符序列已被分析为预处理单词,则下一个预处理单词是可构成预处理单词的最长的字符序列 ,比如, x ++ + ++y 是不符合定义的,x++已被分析为预处理单词,后面的字符构成不了预处理单词
#include<bits/stdc++.h>
using namespace std;

int main(int argc,char *argv[]){
   
    int x = 0, y = 0, c;
    c = x ++ + ++ y;
    cout << x  << endl << y << endl << c;  //输出 1 1 1 
    return 0;
}

token
在这里插入图片描述
pp-token
在这里插入图片描述

2、关键字

关键字 说明
auto 声明自动变量
break 跳出当前循环
case 开关语句分支
char 声明字符型变量或函数返回值类型
const 定义常量,如果一个变量被 const 修饰,那么它的值就不能再被改变
continue 结束当前循环,开始下一轮循环
default 开关语句中的"其它"分支
do 循环语句的循环体
double 声明双精度浮点型变量或函数返回值类型
else 条件语句否定分支(与 if 连用)
enum 声明枚举类型
extern 声明变量或函数是在其它文件或本文件的其他位置定义
float 声明浮点型变量或函数返回值类型
for 一种循环语句
goto 无条件跳转语句
if 条件语句
int 声明整型变量或函数
long 声明长整型变量或函数返回值类型
register 声明寄存器变量
return 子程序返回语句(可以带参数,也可不带参数)
short 声明短整型变量或函数
signed 声明有符号类型变量或函数
sizeof 计算数据类型或变量长度(即所占字节数)
static 声明静态变量
struct 声明结构体类型
switch 用于开关语句
typedef 用以给数据类型取别名
unsigned 声明无符号类型变量或函数
union 声明共用体类型
void 声明函数无返回值或无参数,声明无类型指针
volatile 说明变量在程序执行中可被隐含地改变
while 循环语句的循环条件

3、标识符

描述
标识符是由非数字字符(包括下划线和大小写字母)及数字构成的序列,其第一个字符应是非数字字符,不同的标识符取决于有效字符的不同
分类

  1. 结构成员或标记
  2. 联合成员或标记
  3. 枚举成员或标记,枚举成员称枚举常量
  4. 自定义类型名
  5. 标签名
  6. 宏名或宏形参

约束

  1. 组成标识符的字符序列不应与组成关键字的字符序列相同
  2. 标识符最大长度没有具体限制。标准规定宏名或无外部链接的标识符前31个字符定为有效字符(不忽略大小写),外部链接的标识符前6个字符定为有效字符(可忽略大小写),具体由实现定义,存在有效字符相同、非有效字符不同的两个标识符的行为未定义

3.1、标识符作用域

3.1.1、作用域范围

  1. 函数(function)作用域:仅标签具有函数作用域,通过冒号隐式声明(go to语句)
  2. 文件(file)作用域:声明标识符的声明符或类型说明符出现在所有块或参数列表之外,在翻译单元的末尾终止,比如全局变量
  3. 块(block)作用域:声明标识符的声明符或类型说明符出现在块内或函数定义中的参数声明列表内,终止于},比如,函数形参
  4. 函数原型(function prototype)作用域:如果声明标识符的声明符或类型区分符出现在函数原型(不是函数定义的一部分)的参数声明列表中,在函数声明的末尾终止
#include<bits/stdc++.h>
using namespace std;

int test1(int a, int b);        //a、b函数原型作用域
                                //buf1、buf2块作用域
int test1(int buf1, int buf2){
     
    return buf1 + buf2;
}
int N = 100, M;              //M, N文件作用域

int main()
{
   
    label: M = test1(N, M);     //label函数作用域
    if(M < 1000){
   
        goto label;
    }
    cout << M;              //输出 1000
    return 0;
}

  1. 结构、联合和枚举标记的作用域在声明标记的类型区分符时,标记出现后立即开始
  2. 每个枚举常量的作用域都在其在枚举符列表中定义常量的枚举符后立即开始
  3. 任何其他标识符的作用域都是在其声明程序完成后立即开始
#include<bits/stdc++.h>
using namespace std;

enum test{
         //枚举作用域开始
    a = 100,  //枚举常量作用域开始
    b
}num;
int main()
{
   
    cout << 100 + num;   
    return 0;
}

3.1.2、链接(linkage)

通过链接可在不同作用域或同一作用域,引用同一个对象或函数

  1. 外部链接(external):一组翻译单元中指向同一个对象或函数,只需extern,若文件范围内有可见声明则与其具有相同的链接,若文件范围内没有可见声明则为外部链接
  2. 内部链接(internal):一个翻译单元中指向同一个对象或函数,文件作用域 + static,作用:别的文件不能访问
  3. 无链接(none):指向独一无二的实体,声明为对象或函数以外的任何标识符;声明为函数参数的标识符;没有extern的块内声明的对象标识符
  4. 如果在翻译单元中,同一标识符同时出现在内部和外部链接中,则该行为未定义
  5. 函数标识符和文件作用范围的对象默认外部链接
//test2.cpp
int b = 100;

//test1.cpp
#include<bits/stdc++.h>
using namespace std;
static int b = 1000;
void test_fuc(){
   
    extern int b;
    cout << b;
}
int main()
{
   
    test_fuc();
    return 0;
}
//多文件编译$g++ -o test test1.cpp test2.cpp,输出1000,有extern但是文件作用范围内有可见声明,所以extern b的链接是内部链接
//将test1的static int b = 1000;语句删除,再次运行输出100,有extern且文件作用范围内没有可见声明,所以extern b的链接是外部链接
//将test2的int b = 100;语句前加上static,再次编译,编译失败

3.1.3、命名空间

不同类别的标识符具有不同的命名空间

类别 消除歧义方法
标签名称 通过标签声明和使用的语法消除歧义
结构、联合和枚举的标记 通过跟随关键字struct、union或enum来消除歧义
结构或联合的成员 通过. 或 ->运算符访问成员时使用的表达式类型消除歧义
所有其他标识符称为普通标识符 在普通声明器中声明或作为枚举常量声明
//正常编译
#include<bits/stdc++.h>
using namespace std;
struct test1
{
   
    int a = 1;
}test1
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值