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的更多相关文章

  1. C和指针笔记 3.6链接属性

    链接属性决定如何处理在不同文件中出现的标识符.标识符的作用域也它的链接属性有关,但这两个属性并不相同. 没有链接属性的标识符(none)总是被当作单独的个体,也就是说该标识符的多个声明被当作独立不同的 ...

  2. C和C指针小记(十六)-动态内存分配

    动态内存分配 1.1 为什么使用动态内存分配 直接声明数组的方式的缺点: 1) 声明数组必须指定长度限制.无法处理超过声明长度的数组. 2) 如果声明更大的常量来弥补第一个缺点,会造成更多的内存浪费. ...

  3. C和指针 第六章 数组名与指针

    指针的算术运算符是指针和数组之间的一种关联,但不是唯一关联: 可以使用数组名作为指向数组第一个元素的指针,但是不可以给数组名赋新的值. //如下声明a int a[10]; //用a作为指向数组第一个 ...

  4. C语言指针与数组的定义与声明易错分析

    部分摘自<C语言深度解剖> 1.定义为数组,声明为指针 在文件1中定义: char a[100]; 在文件2中声明: extern char *a; //这样是错误的 这里的extern告 ...

  5. C和C指针小记(十八)-使用结构和指针-双向链表

    1.双链表 1.1 双向链表的声明 在一个双链表中,每个节点都包含两个指针--指向前一个节点的指针和指向后一个节点的指针. 声明 typedef struct NODE { struct NODE * ...

  6. C和C指针小记(十七)-使用结构和指针-链表

    1.链表 链表(linked list)即使是一些包含数据的独立数据结构的(Node)集合. 链表中的每个节点通过链或指针链接在一起. 程序通过指针访问链表中的节点. 节点通常是动态分配的,但也有由节 ...

  7. C和C指针小记(十五)-结构和联合

    1.结构 1.1 结构声明 在声明结构时,必须列出它包含的所有成员.这个列表包括每个成员的类型和名称. struct tag {member-list} variable-list; 例如 //A s ...

  8. C和C指针小记(十三)-数组

    1.1 一维数组 一维数组的声明: int a[10]; 这里a就是一个数组. 数组a的类型就是一个指向整型的常量指针. 但是数组和指针是**不相同**的. **数组具有特定数量的元素,而指针只是一个 ...

  9. Android JNI编程(六)——C语言函数指针、Unition联合体、枚举、Typedef别名、结构体、结构体指针

    版权声明:本文出自阿钟的博客,转载请注明出处:http://blog.csdn.net/a_zhon/. 目录(?)[+] 一:函数指针 1.函数指针顾名思义就是定义一个指针变量指向一个函数,和一级指 ...

随机推荐

  1. oracle本地编译问题

    oracle10.2: --将过程重新编译为本地编译方式,提示有编译错误,经查提示未设置plsql_native_library_dir 参数 SQL> alter procedure p_xx ...

  2. [转]ssh和SSH服务(包含隧道内容)

    本文对SSH连接验证机制进行了非常详细的分析,还详细介绍了ssh客户端工具的各种功能,相信能让各位对ssh有个全方位较透彻的了解,而不是仅仅只会用它来连接远程主机. 另外,本人翻译了ssh客户端命令的 ...

  3. Eclipse插件的安装(手动安装),以安装SVN插件和中文语言包为例

    Eclipse 插件的手动配置 今天自己亲自手动安装了Eclipse插件,参考了网络上的一些文章,总结一下安装的方法.下面通过两个例子来分享一下自己的收获. 例1:SVN插件安装 1.在Eclipse ...

  4. vue中使用localstorage

    1.store.js(读取写入到localstorage) const STORAGE_KEY="todos-vuejs" export default{ fetch(){ ret ...

  5. 【iCore1S 双核心板_FPGA】例程八:触发器实验——触发器的使用

    实验现象: 在本实验中,将工程中的D触发器.JK触发器实例化,对应其真值表,用signal对其进行 检验,利用SignaTap II观察分析波形. 核心代码: module D( input CLK, ...

  6. Java知多少(7)类与对象

    Java是一门面向对象的编程语言,理解Java,首先要理解类与对象这两个概念. Java中的类可以看做C语言中结构体的升级版.结构体是一种构造数据类型,可以包含不同的成员(变量),每个成员的数据类型可 ...

  7. CMMI的敏捷开发

  8. 大数据基础篇----jvm的知识点归纳-5个区和垃圾回收机制

    一直对jvm看了又忘,忘了又看的.今天做一个笔记整理存放在这里. 我们先看一下JVM的内存模型图: 上面有5个区,这5个区干嘛用的呢? 我们想象一个场景: 我们有一个class文件,里面有很多的类的定 ...

  9. Android短信监听实现,及Android4.4之后短信机制变更

    前阵子公司有一个项目,简单的监听短信应用,功能只有如下两个: 1.监听短信并获取短信内容上传服务器: 2.从服务器获取短信内容,发送出去    按照传统的思路,监听短信我们有两种方式:第一种是使用广播 ...

  10. 浅析C#中的结构体和类

    类和结构是 .NET Framework 中的常规类型系统的两种基本构造. 两者在本质上都属于数据结构.封装着一组总体作为一个逻辑单位的数据和行为. 数据和行为是该类或结构的"成员" ...