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. Jason 和 Java 对象转化示例

    1.工程 2.代码: JsonUtil.java package com.my.json; import java.util.ArrayList; import java.util.List; imp ...

  2. 【XMPP】基于XMPP的即时通讯解决方案

    什么是XMPP 介绍XMPP之前,先来看看GTalk. GTalk是Google推出的IM(Instant Messaging,即时通讯)软件,类似于QQ和MSN. 从技术角度来说,GTalk与QQ和 ...

  3. 使用apktool.jar工具反编译和回编译Android APK 终端命令模式

    1.工具准备 工具可以网上搜索下载新版本,也可以从这里Download:https://github.com/FlymeOS/tools/blob/lollipop-5.1/reverses/apkt ...

  4. No service of type Factory<LoggingManagerInternal> available in ProjectScopeService

    导入GitHub上下载的项目时报错 No service of type Factory<LoggingManagerInternal> available in ProjectScope ...

  5. linux 防火墙 ufw使用

    ufw是ubuntu是默认的防火墙配置工具,相对于iptables,ufw使用更加简单 ufw基本操作   1 []是代表可选内容,需要root权限 ufw [--dry-run] enable|di ...

  6. 关于Unity中NGUI的3D角色血条的实现

    首先要到Unity的Assets Store里面去下载一个扩展的Package叫NGUI HUD Text v1.13(81),注意如果没有安装NGUI就必须先安装NGUI插件,否则会用不了,因为HU ...

  7. Java如何在指定端口创建套接字?

    在Java编程中,如何在指定端口创建套接字并连接到指定服务器的端口? 下面的例子演示了Socket类的Socket构造函数,并且使用getLocalPort(),getLocalAddress(),g ...

  8. ubuntu 创建swap分区

    通常,Linux系统中swap分区可以通过两种方式指定,分别为:一.在磁盘分区的时候格式化一个swap分区:二.在文件系统中创建一个swap文件作为swap分区.此文主要介绍第二种方式.步骤如下: 1 ...

  9. [Stats385] Lecture 03, Harmonic Analysis of Deep CNN

    大咖秀,注意提问环节大家的表情,深入窥探大咖的心态,很有意思. 之前有NG做访谈,现在这成了学术圈流行. Video: https://www.youtube.com/watch?v=oCohnBbm ...

  10. 15适配器模式Adapter

    一.什么是适配器模式 Adapter模式也叫适配器模式,是构造型模式之一 ,通过Adapter模式可以改变已有类(或外部类)的接 口形式. 二.适配器模式应用场景 在大规模的系统开发过程中,我们常常碰 ...