C和C指针小记(六)-基本声明、指针声明、typedef 、常量、作用域、链接属性、存储类型、static
1、变量的声明
声明变量的基本形式:
说明符号(一个或者多个) 声明表达式列表
说明符 (specifier) 包含一些关键字,用于描述被声明的标识符的基本类型,它也可用户改变标识符的缺省存储类型和作用域.
如:
int i;
char j, k, l;
修改变量的长度或者是否为有符号数的关键字:
//short long signed unsigned
unsigned short int a;
unsigned short a;
相等的整型说明
有符号 | 无符号 |
---|---|
short signed short | unsigned short |
short int signed short int | unsigned short int |
int signed int | unsigned int |
signed | unsigned |
long signed long | unsigned long |
long int signed long int | unsigned long int |
2、指针的声明
几个需要注意的点
//正常的声明一个指向整型指针
int *a;
//也可以这样写, *与int 类型标识符贴近.
int* a;
//需要注意的是 只有b 是整型指针, c,d是整型
int *b, c, d;
//只有*紧贴变量名时才使得 b,c,d 都是指向整型的指针
int *b, *c, *d;
//声明+初始化一个字符串
char *message = "hello world!";
//上句相当于这两行代码
char *message;
message = "hello world!";
3、typedef
typedef 允许程序员为各种数据类型定义新的名字
例如:
//声明一个指向字符的指针prt_to_char
char *prt_to_char;
//用typedef 把 prt_to_char作为指向字符的指针类型的新名字.
typedef char *ptr_to_char;
//可以使用这个新名字定义 指向字符的指针
ptr_to_char a;
注意:应该使用typedef 而不是 #define 来创建新的类型名 ,因为后者无法处理指针类型
定义复杂的类型名字时应该使用typedef 如:函数指针或者指向数组的指针
4、常量
ANISI C允许声明常量.
常量的样子和变量完全一样,只是不能被修改.声明时使用const关键字.
如
//常量的声明,但是无法被更改
int const a;
const int a;
//所以常量声明和定义是一起的
int cosnt a = 1;
//当涉及指针变量时,需要注意
//pi 是一个普通的指向整型的指针,
int *pi;
//pic 是一个指向整型常量的指针.你可以修改指针的值,但你不能修改它所指向的值.
int const *pic;
//pcc 为指向整型的常量指针.此时指针是常量,它的值无法被修改,但你可以修改它所指向的整型的值.
int * const pcc;
//cc无论是指针还是它所指向的值都是常量,不允许修改
int const * const * cc;
*cosnt 的结合是从右往左的,如 int const pcc; const修饰,指针是不能被修改的.又如 int const pic ,指针所指的值是不能被修改的
#define 也是可以定义常量的, 用字面值的地方都可以用 #define 来定义
5、作用域 scope
变量在程序的某个部分被声明的时候,它只有在程序的一定区域才能被访问. 这个区域由标识符作用域决定.
编译器可以确认4中不同类型的作用域:
文件作用域、函数作用域、代码块作用域、原型作用域
6、链接属性
链接属性一共有3种:external(外部)、internal(内部)、none(无)
没有链接属性的标识符(none )总是被当作单个个体,也就是该标识符的多个声明被当作独立不同的实体.
属于internal链接属性的标识符在同一个源文件的所有声明中都指向同一个实体,但位于不同源文件的多个声明则分属不同的实体.
属于 external 链接属性的标识符不论声明多少次,位于几个源文件都标示同一个实体.
关键字 extern 和 static 用于在声明中修改标识符的链接属性.如果某个声明在正常情况下具有 extrenal 链接属性,在它前面加上 static 关键字可以使它的链接属性变为 internal.
如
// b 的作用域变为该源文件所私有
static int b;
//函数 foo的作用域为它所在的源文件所私有, 可以防止它被其他源文件调用
static int foo(int d);
7、存储类型
变量的存储类型是指存储变量值的内存类型.
存储类型决定来变量何时创建、何时销毁、以及它的值保持多久.
变量存储的三个地方:普通内存、运行时堆栈、硬件寄存器.
变量的缺省存储类型取决于它的声明位置.
凡是在任何代码块之外声明的变量,总是存储与静态内存中,也就是不属于堆栈的内存,这类变量称为静态(static)变量.对于这类变量,你无法为他们指定其他存储类型. 静态类型在程序运行之前创建,在程序的整个执行期间始终存在.它始终保持原先的值,除非给它赋一个不同的值或者程序结束.
在代码块内部声明的变量的缺省存储类型都是自动(automatic), 也就是说它存储于堆栈中,称为自动(auto)变量.一个函数被多次调用,它内部的自动变量会被多次创建和销毁.对于在代码块内部声明的变量,如果给它加上static关键字,可以使它的存储类型从自动变为静态.具有静态存储类型的变量在整个程序执行过程中一致直存在,而不仅仅在声明它的代码块的执行时存在.
注意:修改变量的存储类型,并不代表修改变量的作用域,它仍然只能在该代码内部按名字访问.函数的形式参数不能声明为静态,因为实参总是在堆栈中传递参数,用于支持递归
关键字register可用于自动变量的声明,提示它们应该存储于机器的硬件寄存器而不是内存中,这类变量称为寄存器变量.通常,寄存器变量比存储于内存的变量访问起来效率更高.但是编译器并不一定要理睬 register关键字,如果有太多的变量被声明为 register, 它只选取前几个实际存储于寄存器中,其余的就按照普通自动变量处理.
8、static 关键字
特别提醒: 不同的上下文环境,static关键字具有不同的作用
-当它用与函数定义时,或用于代码块之外的变量声明时,static 关键字用于修改标识符的链接属性, 从 external 改为 internal, 但标识符的存储类型和作用域不受影响.用这种方式声明的函数或变量只能在声明他们的源文件内部访问.
-当它用于代码块内部的变量时, static关键字用于修改变量的存储类型,从自动变量修改为静态变量,但变量的链接属性和作用域不受影响.用这种方式声明的变量在程序执行之前创建,并在程序的整个执行期间一致存在,而不是每次在代码块开始执行是创建,在代码块执行完毕后销毁.
9、作用域、链接属性、存储类型总结
变量类型 | 声明的位置 | 是否存于堆栈 | 作用域 | 如果声明为static |
---|---|---|---|---|
全局 | 所有代码块之外 | 否 | 从声明处到文件尾 | 不允许从其他源文件访问 |
局部 | 代码块起始处 | 是 | 整个代码块 | 变量不存储于堆栈中,它的值在真个执行期一直保持 |
形式参数 | 函数头部 | 是 | 整个函数 | 不允许 |
C和C指针小记(六)-基本声明、指针声明、typedef 、常量、作用域、链接属性、存储类型、static的更多相关文章
- C和指针笔记 3.6链接属性
链接属性决定如何处理在不同文件中出现的标识符.标识符的作用域也它的链接属性有关,但这两个属性并不相同. 没有链接属性的标识符(none)总是被当作单独的个体,也就是说该标识符的多个声明被当作独立不同的 ...
- C和C指针小记(十六)-动态内存分配
动态内存分配 1.1 为什么使用动态内存分配 直接声明数组的方式的缺点: 1) 声明数组必须指定长度限制.无法处理超过声明长度的数组. 2) 如果声明更大的常量来弥补第一个缺点,会造成更多的内存浪费. ...
- C和指针 第六章 数组名与指针
指针的算术运算符是指针和数组之间的一种关联,但不是唯一关联: 可以使用数组名作为指向数组第一个元素的指针,但是不可以给数组名赋新的值. //如下声明a int a[10]; //用a作为指向数组第一个 ...
- C语言指针与数组的定义与声明易错分析
部分摘自<C语言深度解剖> 1.定义为数组,声明为指针 在文件1中定义: char a[100]; 在文件2中声明: extern char *a; //这样是错误的 这里的extern告 ...
- C和C指针小记(十八)-使用结构和指针-双向链表
1.双链表 1.1 双向链表的声明 在一个双链表中,每个节点都包含两个指针--指向前一个节点的指针和指向后一个节点的指针. 声明 typedef struct NODE { struct NODE * ...
- C和C指针小记(十七)-使用结构和指针-链表
1.链表 链表(linked list)即使是一些包含数据的独立数据结构的(Node)集合. 链表中的每个节点通过链或指针链接在一起. 程序通过指针访问链表中的节点. 节点通常是动态分配的,但也有由节 ...
- C和C指针小记(十五)-结构和联合
1.结构 1.1 结构声明 在声明结构时,必须列出它包含的所有成员.这个列表包括每个成员的类型和名称. struct tag {member-list} variable-list; 例如 //A s ...
- C和C指针小记(十三)-数组
1.1 一维数组 一维数组的声明: int a[10]; 这里a就是一个数组. 数组a的类型就是一个指向整型的常量指针. 但是数组和指针是**不相同**的. **数组具有特定数量的元素,而指针只是一个 ...
- Android JNI编程(六)——C语言函数指针、Unition联合体、枚举、Typedef别名、结构体、结构体指针
版权声明:本文出自阿钟的博客,转载请注明出处:http://blog.csdn.net/a_zhon/. 目录(?)[+] 一:函数指针 1.函数指针顾名思义就是定义一个指针变量指向一个函数,和一级指 ...
随机推荐
- Jason 和 Java 对象转化示例
1.工程 2.代码: JsonUtil.java package com.my.json; import java.util.ArrayList; import java.util.List; imp ...
- 【XMPP】基于XMPP的即时通讯解决方案
什么是XMPP 介绍XMPP之前,先来看看GTalk. GTalk是Google推出的IM(Instant Messaging,即时通讯)软件,类似于QQ和MSN. 从技术角度来说,GTalk与QQ和 ...
- 使用apktool.jar工具反编译和回编译Android APK 终端命令模式
1.工具准备 工具可以网上搜索下载新版本,也可以从这里Download:https://github.com/FlymeOS/tools/blob/lollipop-5.1/reverses/apkt ...
- No service of type Factory<LoggingManagerInternal> available in ProjectScopeService
导入GitHub上下载的项目时报错 No service of type Factory<LoggingManagerInternal> available in ProjectScope ...
- linux 防火墙 ufw使用
ufw是ubuntu是默认的防火墙配置工具,相对于iptables,ufw使用更加简单 ufw基本操作 1 []是代表可选内容,需要root权限 ufw [--dry-run] enable|di ...
- 关于Unity中NGUI的3D角色血条的实现
首先要到Unity的Assets Store里面去下载一个扩展的Package叫NGUI HUD Text v1.13(81),注意如果没有安装NGUI就必须先安装NGUI插件,否则会用不了,因为HU ...
- Java如何在指定端口创建套接字?
在Java编程中,如何在指定端口创建套接字并连接到指定服务器的端口? 下面的例子演示了Socket类的Socket构造函数,并且使用getLocalPort(),getLocalAddress(),g ...
- ubuntu 创建swap分区
通常,Linux系统中swap分区可以通过两种方式指定,分别为:一.在磁盘分区的时候格式化一个swap分区:二.在文件系统中创建一个swap文件作为swap分区.此文主要介绍第二种方式.步骤如下: 1 ...
- [Stats385] Lecture 03, Harmonic Analysis of Deep CNN
大咖秀,注意提问环节大家的表情,深入窥探大咖的心态,很有意思. 之前有NG做访谈,现在这成了学术圈流行. Video: https://www.youtube.com/watch?v=oCohnBbm ...
- 15适配器模式Adapter
一.什么是适配器模式 Adapter模式也叫适配器模式,是构造型模式之一 ,通过Adapter模式可以改变已有类(或外部类)的接 口形式. 二.适配器模式应用场景 在大规模的系统开发过程中,我们常常碰 ...