文档章节

C和指针---第三章:数据

fzyz_sb
 fzyz_sb
发布于 2013/09/12 21:13
字数 2041
阅读 61
收藏 0

3.1 基本数据类型

在C语言中,仅有4种基本数据类型---整型,浮点型,指针和聚合类型(如数组和结构等)

3.1.1 整型家族

1. 整型字面值:包括正常的十进制,八进制和十六进制,字符常量(‘a’)

2. 枚举类型

3.1.2 浮点类型

3.1.3 指针


3.2 基本声明

说明符(一个或多个) 声明表达式列表

说明符包含了一些关键字,用于描述被声明的标识符的基本类型。说明符也可以用于改变标识符的缺省存储类型和作用域。

3.2.3 声明指针

在指针的使用中,要注意字符串(本身自带*和真正的指针)之间的区别,比如:

#include <stdio.h>
#include <stdlib.h>

main()
{
	int a = 12;
	char *str = "";
	int *pa = &a;
	printf("%d\n", *pa);
	printf("%x\n", pa);

	str = "hello world";
	printf("%s\n", str);	//注意:不是*str
	printf("%x\n", str);	//注意:这里不是&str
}
注意:这里str即代表字符串,又代表地址。即字符串是特殊的指针。

即以下两种声明等价:

char *message = "hello world";
char *message;
message = "hello world";

3.3 typedef

typedef允许为各种数据类型定义新名字。

typedef char *ptr_to_char;
则ptr_to_char等价于char *;

3.4 常量

我们可以使用const来声明常量

int const a;
有两种方法可以让常量一开始就有值:

1. 声明时对其进行初始化。

2. 在函数中声明为const的形参在函数被调用时会得到实参的值。

如果是指针的话,则有趣多了。

int const *pci;
则是一个指向整型常量的指针。你可以修改指针的值,但你不能修改它所指向的值。

我们可以这样理解,const修饰的是int,而int则代表的是其指针所指向的值的类型。下面代码可说明一切:

#include <stdio.h>
#include <stdlib.h>

main()
{
	int a = 12;
	int b = 14;
	int const *p = &a;
	p = &b;			//修改指针的值--right
	printf("%d", *p);
	*p = 24;		//修改指针所指向的值--error
	printf("%d", *p);
}
而:
int * const cpi;
则声明cpi为一个指向整型的常量指针。此时指针是常量,它的值是无法修改,但我们可以修改它所指向的整型的值。我们可以这样理解,const修饰的是int *;
#include <stdio.h>
#include <stdlib.h>

main()
{
	int a = 12;
	int b = 14;
	int * const p = &a;
	p = &b;			//修改指针的值--error
	printf("%d", *p);
	*p = 24;		//修改指针所指向的值--right
	printf("%d", *p);
}
备注:这里指针指的是p,而不是*p.

#define指令是另一种创建名字常量的机制。

#define MAX_ELEMENTS 50
int const max_elements = 50;
在这种情况下,使用#define比使用const变量更好。因为只要允许使用字面值常量的地方都可以使用前者,比如声明数组的长度。const常量只能用于允许使用变量的地方。

3.5 作用域

当变量在程序的某个部分被声明时,它只有在程序的一定区域才能被访问。这个区域由标识符的作用域决定。标识符的作用域就是程序中该标识符可以被使用的区域。例如,函数的局部变量的作用域局限于该函数的函数体。这个规则意味着两点。首先,其他函数都无法通过这些变量的名字访问它们,因为这些变量在它们的作用域之外便不再有效。其次,只要分属不同的作用域,你可以给不同的变量起同一个名字。

编译器可以确认4种不同类型的作用域---文件作用域,函数作用域,代码块作用域和原型作用域。

3.5.1 代码块作用域

位于一对花括号之间的所有语句称为一个代码块。任何在代码块的开始位置声明的标识符都具有代码块作用域,表示它们可以被这个代码块中的所有语句访问。

3.5.2 文件作用域

任何在所有代码块之外声明的标识符都具有文件作用域,它表示这些标识符从它们的声明之处直到它所在的源文件结尾处都是可以访问的。

3.5.3 原型作用域

原型作用域只适用于在函数原型中声明的参数名。

3.5.4 函数作用域

用于goto语句的标签-----永远也不要用到goto语句。


3.6 链接属性

标识符的链接属性决定如何处理在不同文件中出现的标识符。标识符的作用域与它的链接属性有关,但这两个属性并不相同。

链接属性一共有3种---external(外部),internal(内部)和nont(无)。没有链接属性的标识符总是被当作单独的个体,也就是说该标识符的多个声明被当作独立不同的实体。属于internal链接属性的标识符在同一个源文件内的所有声明中都指同一个实体,但位于不同源文件的多个声明则分割不同的实体。最后,属于external链接属性的标识符不论声明多少次,位于几个源文件都表示同一个实体。

typedef char *a;
int b;
int c(int d){
	int e;
	int f(int g);
	...
}
具有文件作用域的变量(函数名特殊,但也具有文件作用域)的链接属性为external。

所以b,c,f的链接属性为external。

关键字extern和static用于在声明中修改标识符的链接属性。如果某个声明在正常情况下具有external属性,在它前面加上static关键字可以使它的链接属性变为internal。但如果对函数内的局部变量(链接属性为none)前加上static,则链接属性依旧为none,它具有类似函数局部作用域的“internal”属性(注意:internal属性具有文件作用域)。

extern并不会改变原本声明为internal属性的变量的链接属性:

static int i;
int func(){
	int j;
	extern int k;
	extern int i;
}
其中i依旧是internal属性。


3.7 存储类型

常量的存储类型是指存储变量值的内存类型。变量的存储类型决定变量何时创建,何时销毁以及它的值将保持多久。有三个地方可以用于存储变量:普通内存,运行时堆栈,硬件寄存器。

变量的缺省存储类型取决于它的声明位置。凡是在任何代码块之外声明的变量总是存储于静态内存中,也就是不属于堆栈的内存,这类变量称为静态变量。对于这类变量,你无法为它们指定其他存储类型。静态变量在程序运行之前创建,在程序的整个执行期始终存在。它始终保持原想的值,除非给它赋一个不同的值或者程序结束。

在代码内部声明的变量的缺省存储类型是自动的,也就是说它存储于堆栈中,称为自动变量。

如果自动变量加上static,则变成了静态变量。

3.8 static关键字

当static用于函数定义时,或用于代码块之外的变量声明时,static关键字用于修改标识符的链接属性,从external改为internal,但标识符的存储类型和作用域不受影响。用这种方式声明的函数或变量只能在声明它们的源文件中访问。

当它用于代码块内部的变量声明时,static关键字用于修改变量的存储类型,从自动变量修改为静态变量,但变量的链接属性和作用域不受影响。用这种方式声明的变量在程序执行之前创建,并在程序的整个执行期间一直存在,而不是每次在代码块开始执行时创建,在代码块执行完毕后销毁。

© 著作权归作者所有

共有 人打赏支持
fzyz_sb
粉丝 408
博文 209
码字总数 447144
作品 0
武汉
程序员
《Beginning Linux Programming》读书笔记(四)

1, 读写空指针 先看第一种情况,printf试图访问空指针,以打印出字符串,而sprintf试图向空指针写入字符串,这时,linux会在GNU C函数库的帮助下,允许读空指针,但不允许写空指针。 复制代...

嗯哼9925
01/08
0
0
【objective-c】初次学习objective-c问题汇总... 【暂完,待修改错误】

---------------------------------------------------------------------------------------- 这本书,我已经看过两遍,那两遍都是在买mac pro之前看的,目的是...因为语法怪怪的很有趣。 ...

呢喃的猫咪
2013/06/26
0
2
Modern Fortran Explained学习笔记4

第三章.表达式和赋值语句 今天继续从第三章开始学习,第三章主要讲了表达式和赋值语句,其中最主要的是数组的表达和指针等概念的使用。 需要特别注意的点其实不多,主要的东西都是自动实现的...

粗衣大布裹天涯
2017/10/30
0
0
《数据库索引设计与优化》笔记一

《数据库索引设计与优化》笔记一 码蜂笔记2017-09-289 阅读 索引数据库 第二章 表和索引结构 索引页和表页 目前页的大小一般是 或 的。页的大小决定了一个页可以存储多少个索引行、表行,以及...

码蜂笔记
2017/09/28
0
0
入职学习(2)--一个程序员的成长史(22)

看了代是雄对这几个问题的回复之后,唐师傅叫代是雄先熟悉一下办公的电脑及一些办事流程,他要找一些资料作为培训计划中的材料。 代是雄先到公司的IT网站上去逛了一下,发现上面的东西相当的...

zhouzxi
2017/01/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

OSChina 周三乱弹 —— 公司女同事约我

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @莱布妮子:分享水木年华的单曲《蝴蝶花(2002年大提琴版)》 《蝴蝶花(2002年大提琴版)》- 水木年华 手机党少年们想听歌,请使劲儿戳(这里) ...

小小编辑
8分钟前
12
4
Linux环境搭建 | VMware下共享文件夹的实现

在进行程序开发的过程中,我们经常要在主机与虚拟机之间传递文件,比如说,源代码位于虚拟机,而在主机下阅读或修改源代码,这里就需要使用到 「共享文件」 这个机制了。本文介绍了两种共享文...

良许Linux
今天
5
0
JUC锁框架——AQS源码分析

JUC锁介绍 Java的并发框架JUC(java.util.concurrent)中锁是最重要的一个工具。因为锁,才能实现正确的并发访问。而AbstractQueuedSynchronizer(AQS)是一个用来构建锁和同步器的框架,使用A...

长头发-dawn
今天
3
0
docker中安装了RabbitMQ后无法访问其Web管理页面

在官网找了"$ docker run -d --hostname my-rabbit --name some-rabbit -p 8080:15672 rabbitmq:3-management"这条安装命令,在docker上安装了RabbitMQ,,结果输入http://localhost:8080并不......

钟然千落
今天
4
1
spring-cloud | 分布式session共享

写在前面的话 各位小伙伴,你们有福了,这一节不仅教大家怎么实现分布式session的问题,还用kotlin开发,喜欢kotlin的小伙伴是不是很开心! 以前在写Android的时候,就对客户端请求有一定的认...

冯文议
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部