C和指针学习笔记二:数据的基本知识

一、基本数据类型

四种基本数据类型:整型,浮点型,指针,聚合类型(数组、结构等)。其他所有类型由这四种派生而来。

1、整型

包括:字符、短整型、长整型、整型,都分为signed和unsigned版本。

1.1、int型

长整型 >= 整型,整型 >= 短整型。short int至少16位,long int至少32位,缺省的int长度取决于编译器。

16位,32位,64位操作系统中各类型变量的长度:

16位 32位 64位
char 8位,1个字节 8位,1个字节 8位,一个字节
short int 16位,2个字节 16位,2个字节 16位,2个字节
int 16位,2个字节 32位,4个字节 32位,4个字节
long int 32位,4个字节 32位,4个字节 64位,8个字节
long long 64位,8个字节 64位,8个字节
指针 16位,2个字节 32位,4个字节 64位,8个字节

由此发现不同的操作系统中,各数据类型的长度不一样,这样不方便代码的移植和维护。因此,使用typedef关键字,在各个机器中依据数据的实际长度,来给数据类型起别名,再使用别名来定义变量,这样方便两台不同机器对代码的统一管理。
例如:

在16位机器中定义:

typedef signed char int8;
typedef int int16;
typedef long int int32;

在32位机器中定义:

typedef signed char int8;
typedef short int int16;
typedef int int32;

这样,使用新定义的类型名来定义变量,对变量的长度进行统一的管理,就可以在不修改代码的情况下,在这两台机器间进行代码的移植,而不会出现变量冲突的问题。

1.2、char型

signed一般只用于char,字符本质是小整型值,缺省的char要么是signed,要么是unsigned char,这取决于编译器。

类型 值的最小范围
char 0~127
signed char -127~127
unsigned char 0~255
short int -32767~32767
int -32767~32767
long int -2^31 + 1~ 2^31 - 1
unsigned int 0~65535
unsigned short int 0~65535
unsigned long int 0~ 2^32 - 1
  • 为了提高程序的可移植性,可将存储在char型变量中的值限制在signed char和unsigned char的交集,即0~127中;
  • 当char被具体声明为signed和unsigned时,再对其进行算术运算;
  • 注意库函数的参数列表是signed还是unsigned,防止char不匹配带来兼容性问题。

2、字面值(Literal)

表示常量,尾部可添加一个后缀来改变缺省规则,包括:L,UL。
一般string literal表示字符串常量,char literal表示字符常量

3、枚举类型

enum JAR_TYPE 
{
  CUP, PINT, QUART, HALT_CALLON, CALLON
};
/*表示声明一个枚举类型为Jar_Type;其中的符号名的值默认从0开始,之后依次加一,
可以指定缺省值,未指定缺省值的,其值为前面一个符号名的值加一。*/
enum JAR_TYPE MILK_JUG, GAS_CAN, MEDICINE_BOTTLE; //表示定义枚举类型的变量。
enum JAR_TYPE  
{
  CUP, PINT, QUART, HALT_CALLON, CALLON
}MILK_JUG, GAS_CAN, MEDICINE_BOTTLE; //枚举类型的声明与定义。
enum 
{
  CUP, PINT, QUART, HALT_CALLON, CALLON
}MILK_JUG, GAS_CAN, MEDICINE_BOTTLE; //省略枚举名称,直接定义枚举变量
/*枚举类型引用的两种方法*/
enum JAR_TYPE MILK_JUG = CUP, GAS_CAN = QUART; //法一
enum JAR_TYPE 
{
  CUP, PINT, QUART, HALT_CALLON, CALLON
}MILK_JUG = CUP, GAS_CAN = QUART; //法二

枚举类型实际上就是一个整数,可以进行整数的算术运算,但这么用的话,枚举类型就失去了原来的意义。

4、指针

指针指向一个地址,对指针的间接访问(indirection)可以得到指针所指向的值。
例子:

char *a = "Hello";
  • 语句的执行顺序为:
    1、分配内存给指针变量a;
    2、分配内存给字符串常量Hello;
    3、将字符串常量的首地址赋值给指针变量a。
  • "Hello"为字符串常量,存储在常量区。出现在表达式中时,其代表的值为"Hello"字符串的首地址,并赋值给指针a。
char str[] = "Hello";
  • 新建一个数组空间来存储"Hello",可以整体赋值,也可以单个字符依次赋值:char str[] = {'H','e','l','l','o'};
char str[10];  str = "Hello"; // 错误语句
  • 这条语句是不正确的,"Hello"在赋值语句中表示一个地址的值,而str表示数组的地址值,是一个常量,常量的值不能被改变,所以错误。但是,初始化时对数组赋值字符串是可行的,如第二条语句。

5、常量

一开始改变常量值的两种方法:1、在声明中进行初始化;2、函数声明为const的形参得到实参时

6、浮点数

浮点数的通常以一个小数和一个以某个假定数为基数的指数构成,浮点数的字面值在缺省情况下都是double类型,若加后缀L则为long double类型,若加后缀F则为float类型。
ANSI标准规定:long double至少和double一样长,double至少和float一样长,且所有的浮点数至少可以容纳10^-37 ~ 10^37之间的任何值。

二、作用域(scope)、链接属性(linkage)、存储类型(storage class)

1、作用域:

  • 代码块作用域(block scope):一块花括号之间的语句。
  • 文件作用域(file scope):在代码块之外的声明的标识符都具有文件作用域。
  • 原型作用域(prototype scope):只适用于函数的形参,函数原型中的形参名非必须,不需要与定义中的形参名一致,只要类型一致就行,传入的实参名不需要与形参名一致。
  • 函数作用域(function scope):只适用于goto语句的语句标签,只有一条规则:函数的所有语句标签唯一。

2、链接属性:与作用域有关,但两者不同

决定如何处理各个文件中的标识符。

  • external(外部):表示该标识符能在任何用extern声明该变量的源文件中使用,且表示的是同一个实体。
    文件作用域中的标识符默认为外部链接属性,在任何地方用extern声明的变量都具有外部链接属性(属于第二次声明的除外),用static关键字可以修改其为内部链接属性。

    • 注意:
      • 如果在第二次声明中使用extern关键字,则不会改变标识符的链接属性为外部,只有第一次声明时才有用。

        举例: 若第一次用static声明为内部,则第二次用extern声明时仍为内部链接属性。

      • 函数内部的extern声明,表示此处的全局变量是从另一个区域链接过来的,表示的是另一个区域的实体;

        若没有extern关键字,则表示该变量为函数的局部变量。

  • internal(内部):某一个标识符在同一个源文件的不同声明指向同一个实体,在不同源文件中的多种声明指向不同的实体。
    在全局空间中用static定义变量,或者函数时,表示其为内部链接属性;

    在函数体内用static定义的为none链接属性(因为不能改变其先前的none属性)

  • none(无):函数体内部的标识符默认具有none属性
    用extern声明的局部变量为外部链接属性,不表示局部变量,表示的另一个位置的全局变量;

    用static声明的局部变量不具有链接属性。

3、存储类型(storage class)

  • 静态(static)类型:全局变量或static局部变量,静态内存中
  • 自动(auto)类型:局部变量,存储在堆栈中
  • 寄存器(register)类型:存储于机器硬件寄存器而不是内存中,其访问效率高,将经常访问的变量声明为寄存器类型,以提高访问速度,但太多变量声明为register时,只能选取几个,剩余的为自动变量。因为寄存器数量有限。
  • 外部(external)类型:只能是全局变量,不能是局部静态变量。

变量在内存中存储的位置包括:

  • 堆区(程序员动态分配);
  • 栈区(编译器自动分配);
  • 全区去/静态区(程序结束后由操作系统释放);
  • 常量区(程序员结束后由操作系统释放)。

三、静态变量与动态变量的初始化

等号的意义:

1、在表达式里,是赋值的意思。
2、在变量声明中。 不可以看作是赋值, 只是初始化,作用是告诉编译器如何初始化这个内存空间。

1、静态变量的初始化

可执行文件想要初始化的值,会放当变量使用的位置。当可执行文件载入到内存时,就已经进行了初始化,如果不显式地赋初值,初始化为0。

2、自动变量的初始化

需要更多的开销,因为当程序链接时还无法判断自动变量的存储位置。事实上,函数的局部变量在函数的每次调用中可能占据不同的位置。因此,自动变量没有缺省的初始值,而显式的初始化将在代码块的起始处插入一条隐式的赋值语句。

  • 自动变量初始化的性质:
    • 自动变量初始化较之赋值语句效率并无提高。除了声明为const的变量之外,在声明变量的同时进行初始化和先声明后赋值只有风格只差,并无效率之别。
    • 自动变量所在块每次执行时,都要对自动变量重新赋值。这与静态变量大不相同,后者只是在程序开始执行前初始化一次。
    • 由于初始化在运行时执行,因此可以使用任何表达式作为初始化值。
    • 除非对自动变量显式初始化,否则当自动变量创建时,它的值为任意值,一般为上一次存储在这个位置的变量的值。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容