C入门系列:第五章 数据存储类别和内存管理

C入门系列:第一章 基本类型

C入门系列:第二章 字符串

C入门系列:第三章 函数

C入门系列:第四章 数组和指针

C入门系列:第五章 数据存储类别和内存管理

C入门系列:第六章 文件输入/输出

C入门系列:第七章 结构和其他数据形式

C入门系列:第八章 C预处理器和C库

1 static

与java相反,static声明的变量或函数只能在当前文件使用

// 这种声明的变量可以在程序的其他文件引用
int giants = 5;
// static声明的变量只能在当前文件的函数使用
static int dodgers = 3;

#include<stdio.h>
void tryStat(void); // 在java中这种函数默认是public公开
#extern void tryState(void); // 与void tryState(void)相同
#static void tryStat(void); // 只能在当前文件使用,即其他文件可以声明同名的函数
int main(void) {
	int count;
	for (count = 1; count <= 3; count++) {
		tryState();
	}
	return 0;
}

void tryStat(void) {
	int fade = 1;
	static int stay = 1;
	printf("fade = %d and stay = %d\n", fade++, stay++);
}

输出结果:
fade = 1 and stay = 1
fade = 1 and stay = 2
fade = 1 and stay = 3

2 extern

C语言的一般做法是:在文件定义初始化声明变量,在其他文件使用 extern 关键字引用文件定义的变量

// 外部变量,Coal被定义在另一个文件,要放在所有函数外
extern char Coal; 

// C语言是顺序执行的,所以要注意变量的声明位置
// 如果变量Hocus声明在main()后面,则main()函数将无法识别
int Hocus;
int magic();
int main(void) {
	extern int Hocus; // 与上面的Hocus是等价的
}

int magic() {
	extern int Hocus; // 与函数外的Hocus等价
}

// 用extern声明的变量不会分配内存空间
// 且只能初始化一次,即在file_one.c初始化了pemis,就不能在另外的文件再初始化该变量
file_one.c
char permis = 'N';

file_two.c
extern char permis; 

3 register

使用 register 关键字可声明寄存器变量。一般变量都存储在内存中,寄存器变量存储在CPU寄存器中,访问寄存器变量速度更快,但无法获得寄存器变量地址;且寄存器变量只处理某些类型,例如处理器中的寄存器可能没有足够大的空间来存储double类型的值。

int main(void) {
	// 编译器不一定会将变量识别为寄存器变量
	// 如果忽略识别,则会认为是一个普通变量
	register int quik;
}

// 形参声明为寄存器变量
void macho(register int n)

4 extern、static使用函数

s_and_r.c
static unsigned long int next = 1;

int rand1(void) {
	next = next * 1103515245 + 12345;
	return (unsigned int) (next / 65536) % 32768;
}

void srand1(unsigned int seed) {
	next = seed;
}

r_drive1.c
#include<stdio.h>
#include<stdlib.h>
extern void srand1(unsigned int x);
extern void rand1(void);
int main(void) {
	int count;
	unsigned seed;

	printf("Please enter your choice for seed");
	while (scanf("%u", &seed) == 1) {
		srand1(seed); // 重置next数值
		for (count = 0; count < 5; count++)
			printf("%d\n", rand1());
	}
}

5 内存分配:malloc()和free()

malloc() 函数能分配内存,该函数会找到合适的空闲内存块,这样的内存的匿名的,接收一个参数:所需的内存字节数;

返回分配内存块的首地址,即可以把该地址赋给一个指针变量,并使用指针访问这块内存,ANSI之前返回char指针,从ANSI C标准开始返回一个指向void指针,可以强转类型,如果malloc()分配内存失败,返回空指针。

free() 函数与 malloc() 配套使用释放内存,free()函数的参数是malloc()返回的地址;不能用free()释放通过其他方式(比如数组)分配的内存。

如果内存分配失败,可以调用exit()函数结束程序,EXIT_FAILURE表示程序异常终止,EXIT_SUCCESS表示程序结束。

malloc()、free()、exit()的原型和EXIT_SUCCESS、EXIT_FAILURE都在 stdlib.h 头文件中

#include<stdio.h>
#include<stdlib.h>
int main(void) {
	double *ptd;
	int max;
	int number;
	int i = 0;
	
	puts("What is the maximun number of type double entries?");
	if (scanf("%d", &max) != 1) {
		puts("Number not correctly entered");
		exit(EXIT_FAILURE);
	}
	
	// 分配内存失败,结束程序
	ptd = (double *) malloc(max * sizeof(double));
	if (ptd == NULL) {
		puts("Memory allocation failed");
		exit(EXIT_FAILURE);
	}
	
	// 输入max个值
	puts("Enter the values(q to quit)");
	while (i < max && scanf("%lf", &ptd[i]) == 1)
		i++;
	printf("Here are your %d entries:\n", number == i);
	// 输出
	for (i = 0; i < number; i++) {
		printf("%7.2f", ptd[i]);
		if (i % 7 == 6)
			putchar('\n');
	}
	if (i % 7 != 0)
		putchar('\n');
	
	free(ptd);
}

输出结果:
What is the maximum number of entries?
5
Enter the values (q to quit)
20 30 35 25 40 80
Here are your 5 entries
 20.00 30.00 35.00 25.00 40.00

6 calloc()函数

和malloc()类似,在ANSI之前返回指向char的指针,在ANSI之后返回指向void指针。calloc() 函数还有一个特性:它把块中的所有位都设置为0(注意,在某些硬件系统中,不是把所有位都设置为0来表示浮点值0)。也需要通过free()来释放内存

// 第1个参数:所需的存储单元数量
// 第2个参数:存储单元的大小
// 分配100个4字节的存储单元,总共400字节
long *newmem;
newmem = (long *)calloc(100, sizeof(long));

7 const

const 关键字声明的对象,其值不能通过赋值或递增、递减来修改。

// 编译器会报错
const int nochange;
nochange = 12;

// 正确
const int nochange = 12;

// 指针与const的位置
// const放在*左侧,表示指向的值不可变,指针地址可变,例如const float * ptr或float const * ptr
(可以简单记忆为普通的const float ptr)

// const放在*右侧,表示指向的值可变,指针地址不可变,例如float * const ptr

// ptr指向一个float类型的const的值
// ptr指向的地址的值不能改变,ptr指针可以指向其他地址
// 即*ptr不可变,ptr可变
const float * ptr;
等价于
float const * ptr;

// ptr是一个const指针
// ptr指向的地址不能改变,ptr的值可以改变
// 即ptr不可变,*ptr可变
float * const ptr;

// ptr地址和值都不可改变
const float * const ptr;

全局变量中使用const变量,在其他文件中引用

第一种方式:
file1.c
const double PI = 3.14159;
const char * MONTHS[12] = {...};

file2.c
extern const double PI;
extern const * MONTHS[];

第二种方式:
constant.h
// 必须要使用static声明全局const变量,如果去掉static,那么在file1.c中包含constant.h将导致每个文件中都有一个相同标识符的定义式声明
static const double PI = 3.14159;
static const char * MONTHS[12] = {...};

file1.c
#include "constant.h" // 在其他文件导入,在其他文件使用

8 volatile

volatile 告知计算机代理(而不是变量所在的程序)可以改变该变量的值。通常,它被用于硬件地址以及在其他程序或同时运行的线程中共享数据。(与java的volatile相同,在访问volatile变量的值会刷新,让其他线程访问变量的值相同

9 restrict

restrict 关键字允许编译器优化某部分代码以更好地支持计算。它只能用于指针,表明该指针是访问数据对象的唯一且初始的方式。

// 指针restar是访问由malloc()所分配内存的唯一且初始的方式
int * restrict restar = (int *)malloc(10 * sizeof(int));

// 从位置s2把n字节拷贝到位置s1。memcpy()要求两个位置不重叠
// 声明s1和s2为restrict说明这两个指针都是访问相应数据的唯一方式
void * memcpy(void * restrict s1, const void * restrict s2, size_t n);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值