C语言之声明
C语言之声明
1.声明与定义
声明语法
说明符(说明类型或修改缺省属性) 声明表达式列表
- 说明符
- 类型说明:int, float
- 存储属性:static,auto
- 类型限定:const, volatile
声明 VS 定义
- 说明类型:取值范围和合法操作
- 定义:分配存储空间
2.初始化
显式初始化
- 静态变量(含全局变量):使用常量表达式初始化一次
- 自动变量:每次执行时使用赋值语句初始化
非显式初始化
- 静态变量(含全局变量):编译时初始化,缺省值为0
- 自动变量:运行时初始化,缺省为无效值
3.复杂声明与typedef
复杂声明
左右法则:从最里面的圆括号(未定义的标识符)开始,先看其右边,再看其左边,遇到括号时调转方向。一旦解析完括号的内容即可跳出圆括号,重复该过程直到解析完毕。
int *(*(*f)(int))[10];
// (*f) f是一个指针
// (*f1(int)) f1是一个函数指针,所指向的函数返回值是一个指针,参数是(int)
// int *f2[10] f2是一个数组指针,指向数组 int * a[10]
// 综上,f是一个函数指针,指向函数参数为(int), 返回值为指向 int *a[10]的数组指针,其所指向的数组元素类型为 int*
// pointer to function returning pointer to array[10] of pointer to int
char (*(*x())[])();
// *x(), x是一个函数,返回值类型是一个指针
// *(x1)[], x1是一个指针数组,元素类型是指针
// char x2(), x2是一个函数,返回值类型为char
// 综上,x是一个函数,返回值类型是一个指针数组,其数组元素类型是返回值类型为char的函数的指针
// function returning pointer to array[] of pointer to function returning char
char (*(*x[3])())[5];
// *x[3], x是一个数组,元素类型是指针
// *x1(), x1是一个函数,返回值是指针
// char x2[5], x2是数组,元素类型是char
// 综上,x是一个数组,元素类型是函数指针,该函数返回值类型是数组指针,指向元素类型为char的数组
// array[3] of pointer to function returning pointer to array[5] of char
Unix 系统的 cdecl 程序实现了声明的解析,可参考 comp.sources.unix.newsgroup
typedef
语法和声明类似,将标识符作为类型的别名
1. 让代码更加清晰简洁
定义结构体,联合,枚举等变量
typedef struct student {
char name[];
int score;
} T_Stu, *PT_Stu; T_Stu tStu1 = {"Bob", 78};
PT_Stu ptStu1 = &tStu1; typedef enum color {
red, white, block,
} colot_t;
color_t color1 = red;
简化复杂声明
// int *(*array[10])(int *p);
typedef int *(func_ptr)(int *p);
func_prt array[10];
2. 增加代码的可移植性
int 类型在不同的编译器和平台下所分配的存储字节不同,使用自定义的数据类型而不是内置类型来增强可移植性
#ifdef PIC_16
typedef unsigned long u32 // 2 bytes for int, 4 bytes for long
#else
typedef unsigned int u32 // 4 bytes for both int and long in PIC_32
#endif
typedef 的适用情景
- 创建一个数据类型的别名
- 跨平台的指定长度的类型, u32
- 与操作系统,BSP,网络字节相关的数据类型,如size_t, pid_t等
- 不透明的数据类型,需要隐藏数据结构实现细节,只开放函数接口
避免滥用typedef: 参考 Linux Kernel Documennt的CodingStyle
4.辨析
数组与指针参数
int fun(char *str);
int func(char str[]);
// 二者仅在当前声明上下文一致
数组和指针初始化
char *p = "hello";
char a[] = "hello"; // 特殊形式,等价于 char a[] = {'h', 'e', 'l', 'l', 'o', '\0'};
声明与定义
int a; // 变量的声明和定义
extern int b; // 变量的声明
void f1(void){}; // 函数的声明和定义
void f2(void); // 函数的声明
typedef VS #define
typedef等价于存储类关键字,宏定义只是字符串替换
- typedef 不支持继续使用static等存储类关键字
- 宏定义不支持指针声明
- typedef 具有作用域,宏定义在预处理阶段进行全局替换
#define int *POINTER_TO_INT
POINTER_TO_INT a, b, c; // b, c 无法被声明为指针类型 // 与const关键字
typedef char* PTCHAR1;
#define PTCHAR2 char*; const PTCHAR1 p1; // PTCHAR1作为类型,可与consat调换位置,const修饰p1,指针常量
const PTCHAR2 p2; // 等价于 const char* p2; char可与const调换位置,const修饰(*p2),常量指针
//TODO Linux 内核中的声明,学习Linux源码时
5.参考
- 《C和指针》
- 3.2 声明
- 3.3 typedef
- 13.2 高级声明
- 《嵌入式C语言的自我修养》
- 7.5 typedef
- 7.8.2 复杂声明
- 9.4 头文件的深度解析
- 《C程序设计语言》
- 2.4 声明
- 4.9 初始化
- 5.12 复杂声明
- 6.7 类型定义(typedef)
- 《C专家编程》
- 3 C语言的声明
- 4.3 声明与定义
C语言之声明的更多相关文章
- C语言复杂声明-void (*signal(int sig, void (*handler)(int)))(int);
问题提出 请分析此声明:void (*signal(int sig, void (*handler)(int)))(int); 求解过程 在对上面的例子作分析之前,我们需要了解C语言的声明优先级,&l ...
- 《C专家编程》第三章——分析C语言的声明
前面一章我们已经说过C语言存在的一些问题和它晦涩的地方,让我们对这门神奇的语言有了更深的了解.现在这一章则集中精力来讨论C语言的声明,分为三块,首先是说明C语言声明晦涩难懂的原因和声明是如何形成的,其 ...
- C语言复杂声明
C语言复杂声明 First step int *f(); /* f:是一个函数,它返回一个指向int类型的指针*/ int (*pf)(); /* pf:是一个指向函数的指针,该函数返回一个int类型 ...
- C语言字符串声明
重新学习C语言字符串声明char *a="nihao";char a[]="nihao";什么区别?前者定义的是指针,并且指向字符串常量“nihao”,后者是字 ...
- c语言复杂声明解析
这是个好东西,接触c语言好几年了,第一次看到这东西,惊喜万分. 先提供个分析案例,以后看方便 vector <int> * (*seq_array[]) (int )={func1,fun ...
- C语言指针声明探秘
C语言指针声明探秘
- C语言变量声明内存分配
转载: C语言变量声明内存分配 一个由c/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)— 程序运行时由编译器自动分配,存放函数的参数值,局部变量的值等.其操作方式类似于数据结 ...
- [日常] go语言圣经-声明,变量,赋值,类型,包和文件习题
go语言圣经-声明1.四种类型的声明语句:var.const.type和func,分别对应变量.常量.类型和函数实体对象的声明2.包一级声明语句声明的名字可在整个包对应的每个源文件中访问,局部声明的名 ...
- C语言的声明的优先级规则
C语言的声明的优先级规则如下: A 声明从它的名字开始读取,然后按照优先级顺序依次读取 B 优先级从高到低依次是: B.1 声明中被括号括起来的那一部分 B.2 后缀操作符[圆括号 ()表示这 ...
- 浅谈C语言变量声明的解析
C语言本身提供了一种不甚明确的变量声明方式——基于使用的声明,如int *a,本质上是声明了*a的类型为int,所以得到了a的类型为指向int的指针.对于简单类型,这样声明并不会对代码产生多大的阅读障 ...
随机推荐
- 使用X11进行屏幕转播是否有价值? 最好用的远控软件是什么?
由于有多个主机在使用,而且物理位置不在一起,所以以前往往要使用VNC软件来进行远程连接,但是其延迟比较高,使用感受不是很好,而且由于我所使用的多个主机均是Ubuntu系统,于是想到了是否可以使用X11 ...
- Linux下文件及文件夹权限(学习笔记版)
本文遵循CC 4.0 BY-SA版权协议 注意:本文为学习笔记版,只记录个人觉得重要的部分,内容较为片面. Linux 下文件及文件夹的权限可以表示为rwx这三个字符,r代表read,w代表write ...
- Vue Vine:带给你全新的 Vue 书写体验!
你好,我是 Kagol,个人公众号:前端开源星球. 上个月和 TinyVue 的小伙伴们一起参加了 VueConf 24 大会,有幸认识沈青川大佬,并了解了他的 Vue Vine 项目,Vue Vin ...
- 给我5分钟,保证教会你在vue3中动态加载远程组件
前言 在一些特殊的场景中(比如低代码.减少小程序包体积.类似于APP的热更新),我们需要从服务端动态加载.vue文件,然后将动态加载的远程vue组件渲染到我们的项目中.今天这篇文章我将带你学会,在vu ...
- 白鲸开源CEO郭炜荣获「2024中国数智化转型升级先锋人物」称号
2024年7月24日,由数据猿主办,IDC协办,新华社中国经济信息社.上海大数据联盟.上海市数商协会.上海超级计算中心作为支持单位,举办"数智新质·力拓未来 2024企业数智化转型升级发展论 ...
- LeetCode216.组合总和lll
4.组合总和lll(LeetCode216) 题目叙述: 找出所有相加之和为 n 的 k 个数的组合,且满足下列条件: 只使用数字1到9 每个数字 最多使用一次 返回 所有可能的有效组合的列表 .该列 ...
- 和xshell和crt说再见,认识了一款55k star多端跨平台终端神器,强大酷炫
一.Tabby简介 Tabby(以前称为Terminus)是一款高度可配置的终端仿真器.SSH 和串行客户端.开源且跨平台,支持在Windows.macOS和Linux系统下使用. 源码下载 http ...
- 不是 PHP 不行了,而是 MySQL 数据库扛不住啊
大家好,我是码农先森. 大多数的业务场景下 PHP 还没有达到性能瓶颈,然而 MySQL 数据库就先行驾崩了.但我们总是不分青红皂白,一股脑的把原因归结于是 PHP 语言不行了,每当遇到这种情形我就会 ...
- Linux——添加默认路由(能ping通本网段,但是ping不通其他网段)
2024/07/15 1.问题描述 2.问题处理 3.其他问题 1.问题描述 昨天服务器突然断电,今天重启后,网络出了些问题,具体情况如下: 能ping通本机IP ping不通网关 ping不通本网段 ...
- Windows 7远程桌面连接Ubuntu 18.04
从Windows 7远程到Windows系统比较简单,只要对方电脑开启远程桌面功能就可以了,但Windows 7远程桌面连接到Ubuntu 16.04比较复杂一点,具体操作步骤如下. 1 安装xrdp ...