再议C风格变量声明
NeoRAGEx2002曾经有一篇文章提到这个问题,但是有很多内容并没有包括,例如const和__declspec。
最近我遇到一些这方面的问题,感觉有必要做一个系统性的总结。后来经过一些实验,得出了一些结论,在这里分享给大家。
C风格变量声明
C风格的变量声明,如
extern __declspec(dllexport) void(__stdcall * const p[10])(int a, int b);
和其他语言都不一样,规则很不直观,需要一些理解
要理解它为什么是现在这样,首先需要理解它的思路,最初C的类型的写法,模拟了变量的实际使用
例如
#include <functional>
int add(int a, int b)
{
return a + b;
}
int main(int argc, char **argv)
{
int a[10] = {};
int a0 = a[0];
int *p = &a0;
int p0 = *p;
int (*f)(int a, int b) = add;
int result = (*f)(1, 2);
int result2 = f(1, 2); //使用函数指针时可以将(*f)简记为f,但声明时不能,因为会和函数原型混淆
int g(int a, int b); //函数原型
auto h = static_cast<int (*)(int a, int b)>(f); //转换时,需要用到没有变量名的类型声明,此时只需要去掉变量名本身
auto i = std::function<int(int a, int b)>(h); //std::function的参数是函数本身的类型
typedef int FuncType(int a, int b);
auto j = std::function<FuncType>(i); //可以用typedef来将函数本身的类型起一个名字
return 0;
}
因此,要声明一个变量,可以先写出它的实际的用法,再转换成变量声明
比如说我想要写一个包含10个函数指针元素的数组,函数为(int, int) -> int,可以先写调用
int b = (*a[0])(1, 2);
再从调用写声明
int (*a[10])(int a, int b);
注意C中的运算符结合优先级,首先是按括号,然后是右边的索引[]、函数()、成员.或者->,然后是左边的*
C风格变量声明 - const, method const
int add(int a, int b)
{
return a + b;
}
class A
{
private:
int a{};
int b{};
public:
void foo() const //函数后方的const表示函数调用时this为const的
{
this->a = 0; //编译错误,this为A * const;
b = 0; //编译错误
const_cast<A *>(this)->a = 0; //使用const_cast将this转换为A *则可以编译成功
}
};
int main(int argc, char **argv)
{
//const加一个类型名和类型名加const效果相同
const int a1 = 0;
int const a2 = 0;
//const不与后方的*结合
const int *a3 = 0;
int const *a4 = 0;
a3 = a4; //a3、a4为到不可改变的int的指针,但指针本身可以改变
//const与前方的*结合
int (* const a5) = 0;
int * const a6 = 0;
a5 = a6; //编译错误,a5不可改变
//函数指针加const的规则与正常指针相同
int (* const f)(int a, int b) = add;
//成员函数指针加const的规则与正常指针相同
void (A::* const g)() const = &A::foo;
return 0;
}
C风格变量声明 - extern, __declspec, __stdcall等
extern、__declspec(Visual C++)以及一些其他链接标记,是变量的属性,直接加在最前面
__stdcall(Visual C++)等调用规范,是函数的属性,加在函数名称前面或者函数指针的*前面
这样我们就可以明白下面这个声明的含义
extern __declspec(dllexport) void(__stdcall * const p[10])(int a, int b);
//一个extern __declspec(dllexport)的变量p
//p是一个长度为10的数组,数组的每个元素是void(__stdcall * const)(int a, int b)
//这些元素是一个const的函数指针,函数本身的调用规范是__stdcall
//函数的参数是(int a, int b),返回值是void
再议C风格变量声明的更多相关文章
- 再议Java中的static关键字
再议Java中的static关键字 java中的static关键字在很久之前的一篇博文中已经讲到过了,感兴趣的朋友可以参考:<Java中的static关键字解析>. 今天我们再来谈一谈st ...
- TypeScript 素描-变量声明
博文读自 TypeScript 官方文档而来,不具有学习性,仅是本人学习时记录以供日后翻阅 ,有学习TypeScript的朋友还请去看更为详细的官方文档 /* 变量声明在之前的js中一直是使用var关 ...
- 变量声明---let,const,解构
let在很多方面与var是相似的,但是可以帮助大家避免在JavaScript里常见一些问题. const是对let的一个增强,它能阻止对一个变量再次赋值. 块作用域 当用let声明一个变量,它使用的是 ...
- JavaScript变量声明提前
上周四吃完午饭,leader发了一道JavaScript的题目给我们做,我们Team里面有做前端的,有做后台的,也有做mobile web的,所以大家对题目的理解各自都不一样,然后在QQ讨论组里面进行 ...
- 浅谈C语言变量声明的解析
C语言本身提供了一种不甚明确的变量声明方式——基于使用的声明,如int *a,本质上是声明了*a的类型为int,所以得到了a的类型为指向int的指针.对于简单类型,这样声明并不会对代码产生多大的阅读障 ...
- 变量声明提升 Vs. 函数声明提升
1. 变量声明提升 先看以下代码: 1)var in_window = "a" in window; console.log(in_window); 2)var in_window ...
- Python的类变量和对象变量声明解析
Python的类和C++一样,也都是存在两种类型的变量,类变量和对象变量!前者由类拥有,被所有对象共享,后者由每个对象独有.这里我主要想讨论一下他们的声明办法. 首先说的是对象变量: 只要是声明在类的 ...
- JavaScript中的作用域与函数和变量声明的提升
var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar(); ...
- 【C语言探索之旅】 第一部分第四课第二章:变量的世界之变量声明
内容简介 1.课程大纲 2.第一部分第四课第二章:变量的世界之变量声明 3.第一部分第四课第三章预告:变量的世界之显示变量内容 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布 ...
随机推荐
- 初转java随感(一)程序=数据结构+算法
大学刚学编程的时候,有一句很经典的话程序=数据结构+算法 今天有了进一步认识. 场景: 1.当前局面 (1)有现成的封装好的分页组件 返回结果是page.类型为:Page.包括 page 分页信息,d ...
- geohash基本原理
geohash基本原理是将地球理解为一个二维平面,将平面递归分解成更小的子块,每个子块在一定经纬度范围内拥有相同的编码,这种方式简单粗暴,可以满足对小规模的数据进行经纬度的检索 目录: 经纬度常识 认 ...
- 发布 Ionic iOS 企业级应用
转自:http://www.jianshu.com/p/c12fae498975 Ionic 项目开发完成之后呢,自然就是打包发布了,今天说说 iOS 的打包和发布.iOS 的发布方式分为三种:iOS ...
- Elasticsearch【JAVA REST Client】客户端操作
ES系统作为集群,环境搭建非常方便简单. 现在在我们的应用中,如何对这个集群进行操作呢? 我们利用ES系统,通常都是下面的架构: 在这里,客户端的请求通过LB进行负载均衡,因为操作任何一个ES的实例, ...
- 关于CPLD与FPGA的对比分析
1.PLD/FPGA/CPLD PLD(Programmable Logic Device):可编程逻辑器件,数字集成电路半成品,芯片上按照一定的排列方式集成了大量的门和触发器等基本逻辑元件,使用者按 ...
- ListView addHeaderView 对 position 的影响
1. 在 public View getView(int position, View convertView, ViewGroup parent) 中position 和 是否有headerView ...
- Windows2003 IIS6.0支持32位和64位两种模式的设置方法
IIS 6.0 可支持 32 位和 64 位两种模式.但是,IIS 6.0 不支持在 64 位版本的 Windows 上同时运行这两种模式.ASP.NET 1.1 只在 32 位模式下运行.而 ASP ...
- modelsim操作流程
1.File->Change Directory2.File->New->Library 在弹出的对话框中选择 a new library and a logical mapping ...
- Easyui 小脚本
function addTab(subtitle, url, icon) { if (!$('#tabs').tabs('exists', subtitle)) { $('#tabs').tabs(' ...
- Unity UI on the HoloLens
Following the steps under "Required configuration" will allow Unity UI to continue to work ...