C语言-解释复杂声明
基本术语:
声明符:“int a”就是一个声明符。
标识符: 定义的变量名字,如: int a,那么a就是一个标识符。
1.两个原则:
始终从内往外读声明符,括号优先级高。即先定位用来声明的标识符,并且从此处的开始解释。
例1.声明 char *p。首先确定标识符为p;再解析*,它代表p是指针指向;再解析char,它表示指针指向char类型。即p是指向char类型的指针。
例2.声明 void (*pf)(int)。首先确定标识符为pf,在括号内解析*,pf是指针指向;其次(int),指针指向的类型是有int参数的函数;最后void,函数返回值是void。总结:pf是一个指针,它指向了一个参数是int,返回值是void的函数
在选择符号解析顺序时,始终是先[]和()后是*。如果"*“在标识符左边且”[]"在标识符右边(例如:*p[]),那么标识符表示的是数组,而不是指针。括号同理,它表示的是函数(例如:*p())。
例:void*pf(int)。首先先解析右边的(int),pf是函数,参数是int类型;其次void*,类型为void类型的指针。总结:pf是函数,函数有一个int类型的参数,返回值是void*
复杂点的例子:
int *(*x[10])(void)。首先解析括号内[10],x是数组;其次*,数组元素是指针指向;再解析(void),指针指向不带参数的函数;最后int *,函数返回值是int类型的指针。总结:x是有10个元素的数组,它的每个元素都是一个指针,指针指向参数为空并且返回值是int*的函数
2.typedef
我们定义一个无符号整型变量x,使用:unsigned long int x;。如果要简化unsigned long int 名称,可以使用typedef, 例如:把unsigned long int改名为x,则定义:
typedef unsigned long int x;
此时x不是一个变量,而是一个简化的unsigned long int别名,但也不能再用x做变量名。
简化别名后,下面两个语句作用相同:
x b;
unsigned long int b;
上面提到的int *(*x[10])(void)复杂的声明也同样适用,它要简化为别名x,则定义:
typedef int *(*x[10])(void);
x是个自定义类型。它的类型是有10个元素的数组,数组每个元素都是一个指针,指针指向参数为空并且返回值是int*的函数。下面两个语句作用相同。
x b;
int *(*b[10])(void);
3.const
const修饰变量。使变量的地址在只读段。const char a = ‘a’; 和char const a = 'a’是一样的效果。a初始化时被赋值,a的地址在只读段,a不能再被修改。
const修饰指针变量。既可以修饰指针指向的数据,也可修饰指针本身。直接说个技巧:当const在*右边并挨着标识符时,则修饰的是指针本身;当const在*左边时,修饰指针指向的数据。以程序举例证明:
#include <stdio.h>
const char *str = "abc";
const char * const const_p = str;
const char *p = str;int main(void)
{printf("const pointer address:%p, const_p:%p\n", &const_p, const_p);printf("pointer p address:%p, p:%p\n", &p, p);return 0;
}
输出内容如下:
const pointer address:0x400600, const_p:0x4005f8
pointer p address:0x601038, p:0x4005f8
查看ELF格式文件:
$ readelf -a a.out #
...[Nr] Name Type Address OffsetSize EntSize Flags Link Info Align
...[16] .rodata PROGBITS 00000000004005f0 000005f0000000000000005a 0000000000000000 A 0 0 8
...[25] .data PROGBITS 0000000000601028 000010280000000000000018 0000000000000000 WA 0 0 8
可以从地址分段中看出来:
const_p指向的内容在只读段。const_p的地址也被分配在只读段,所以const_p也不能再被赋值。
p指向的内容在只读段。p的地址被分配在数据段,所以p可以被修改。
注意:如果用win10的WSL运行的话,使用gdb查看运行结果。
C语言-解释复杂声明相关推荐
- 如何读懂 C 语言复杂的声明
如何读懂 C 语言复杂的声明 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 参考<<C专家编程>> 废 ...
- c语言数组的声明和初始化_C声明和初始化能力问题和解答
c语言数组的声明和初始化 This section contains aptitude questions and answers on C language Declarations and Ini ...
- c语言函数调用必须声明void,函数声明-czysocket_dara-ChinaUnix博客
看了C陷阱与缺陷,第一个给我震撼的就是理解函数声明了,下面是我的理解. 1.理解函数声明 为了模拟开机启动时的情形,我们必须设计出一个C语句,以显示调用位于地址0的子例程.调用语句如下: (*(voi ...
- c语言 函数的声明,C语言中的函数声明
看了C陷阱与缺陷,第一个给我震撼的就是理解函数声明了,下面是我的理解. 1.理解函数声明 为了模拟开机启动时的情形,我们必须设计出一个C语句,以显示调用位于地址0的子例程.调用语句如下: (*(voi ...
- c语言里的负数用16进制表示什么,什么是十六进制表达式0x80000000在C语言的枚举声明中的含义...
我正在阅读iPhone示例项目(Xcode IDE,Apple LLVM编译器4.2)的代码.在为iPhone样本项目的外部库(C语言编写)的头文件,有是在枚举类型中声明的一些事件:什么是十六进制表达 ...
- 生成跨语言的类型声明和接口绑定的工具(Djinni )
Djinni 是一个用来生成跨语言的类型声明和接口绑定的工具,主要用于 C++ 和 Java 以及 Objective-C 间的互通. 示例接口定义文件: 1 # Multi-line comment ...
- r语言解释回归模型的假设_模型假设-解释
r语言解释回归模型的假设 Ever heard of model assumptions? What are they? And why are they important? A model is ...
- 定义与声明c语言,c语言定义与声明.ppt
c语言定义与声明 f 变量的定义与声明 什么是变量? 变量的分类 变量的属性 修饰符 变量的声明与定义的关系 变量的定义 变量的声明 总结 什么是变量? 在c语言中就是指内存或寄存器中用一个标识符命名 ...
- 数据结构 -- 魔王语言解释
这是数据结构的实验~~ 这是实现一个魔王语言解释器. 这里是采用栈,队列,线性表的综合实现的. 这个程序没上交,所以是中文注释的. 其实这个程序本身实用性不强,但是是个很不错的题目. Experime ...
最新文章
- SpringBoot第十三篇:springboot集成spring cache
- Spring Boot 2.x基础教程:如何扩展XML格式的请求和响应
- 软件测试学习笔记:找代码中的fault,并设计特定的测试用例
- Lambda表达式常用代码示例
- 用html做一个发送邮件验证,邮件发送还有问题吗?送大家一个写好的类吧,支持stmp认证、HTML格式邮件-PHP教程,PHP应用...
- java mysql 占位符_在Java中编写带占位符的SQL语句
- Arduino--0.91寸OLED液晶屏
- IPV6迎来商业元年 运营商短期盈利模式成难点
- AGC027D - Modulo Matrix
- leetcode 451. 根据字符出现频率排序
- Oracle 20c 新特性:表空间缺省加密算法 TABLESPACE_ENCRYPTION_DEFAULT_ALGORITHM
- java注册系统服务_奇葩需求:springboot项目注册为windows系统服务并设置开机自启...
- 蚂蚁金服数据库性能超甲骨文引热议;三大运营商 5G 预约用户接近 930 万;苹果发布新版 Mac 系统| 极客头条...
- 古文(诗词文)—— 结构模式与复用
- PMP考试今年改革吗?
- Debian 8 安装BtSync
- ROS学习笔记14:ROS摄像头驱动及数据接口
- dne服务器没检测到有响应,设备或资源dns没检测到有响应 网络无法连接
- Fedora修复grub2启动项grub rescue
- 上车了!AR摩托车头盔了解一下?