娓娓道来c指针 (2)内存分配

(2)内存分配

c语言中描述变量的时候常用的两个用语

1.作用域:也叫可见域,指的是变量的作用范围。在哪个范围内,该变量是可见的、可以使用的。

2.生存期:也叫存储期,指的是变量从创建到销毁的生存时间段。

作用域和存在域是两个不同的概念,比如在程序的某个位置,某变量存在(内存中分配了地址)但不可见(不可使用)。

作用域

从作用域看,变量分为以下三种:

1.全局变量

在c语言中,把在任何函数之外声明的变量称为全局变量。一般情况下,全局变量在任何地方都是可见的。当然也有例外,比如在语句块{}内声明了一个同名的局部变量,则该全局变量会暂时不可见。

//全局变量
int foo = 5;
void fun()
{
	printf(" fun()->foo...%d\n", foo);
}
int main()
{
	int bar = 3;
	printf("main()->foo...%d\n", foo);
	printf("main()->bar...%d\n", bar);
	{
		//局部变量,屏蔽同名全局变量foo
		int foo = 6;
		printf("    {}->foo...%d\n", foo);
		//局部变量,屏蔽同名局部变量bar
		int bar = 4;
		printf("    {}->bar...%d\n", bar);
	}
	fun();
	return 0;
}

运行

从运行结果可以看出全局变量的可见范围。当然,如果在全局变量未被声明之前就试图使用它,则也会出错。(这与规则:“未声明,不可使用”有关。)

除此之外,c中的设计思想是:一个全局变量也是一个默认的外部变量(extern)。也就是说,一个全局变量不仅在本文件中是全局可见的,在别的文件中也是可见的。如

//1.c
int foo;

在另一个文件中有

//2.c
int foo;

编译报错:foo被重复定义,命名冲突。

这种默认行为被广为诟病,不少人认为,变量的可见域默认下应仅限于当前文件,需要扩大时,应该由程序员自己控制。并且对于函数,也有同样的默认行为。

如何防止这种行为?

(1)若是确实需要使用一个同名的变量,则可对已存在的同名全局变量用static修饰,使之成为静态的全局变量。这样它的可见域,就仅限于它所在的文件之内。如

//1.c
static int foo; //可见域被限制于本文件内

在另一个文件中重新声明 int foo; 没有问题。

(2)不定义新的,直接使用别的文件中的全局变量。语法是 extern int foo; 关键字 extern 是外部的意思,表明变量 foo,已在别的地方定义,这里只是在使用之前,作一个声明而已,不是重复定义。当然不作此声明也是不可用的,这再次体现了:可见,但不一定可用。

2.文件内部的静态变量

这就是上文中说的静态的全局变量。

3.局部变量

在函数中,或更直接的说是在语句块{}内定义的变量,是局部变量。它的可见域仅限于语句块内,在其它地方无法引用。局部变量在函数被调用时由系统分配存储区,在不同的函数中同名的变量实际上在内存中占不同的单元,因此在不同的函数中可以定义相同名字的局部变量。如函数的形参,main函数中定义的变量都是局部变量。

对作用域进行总结

c语言中存在三种作用域

(1)块作用域

自动变量(auto、register)和内部静态变量(static)具有块作用域,在一个块内声明的变量,其作用域从声明点开始,到该块结束为止。函数定义中声明的形参,其作用域限定在该函数体内,与其他函数中声明的同名变量不是一回事,允许在不同的函数中使用相同的变量名,编译器将为这些变量分配不同的存储单元,不会冲突。

(2)文件作用域

外部静态变量(static)具有文件作用域,从声明点开始到文件末尾,此处所指的文件是编译基本单位—c文件。

(3)全局(程序)作用域

全局变量(extern)具有全局作用域,只要在使用前对其进行声明,便可在程序(由若干个文件组成)的任意位置使用全局变量。

生存期

从生存期看,分为以下三种:

1.静态变量(static variable)

全局变量和指定static的局部变量,都具有静态存储期。它们从程序开始一直到程序结束都存在,故被统称为静态变量。

2.自动变量(auto variable)

没有被指定为static的局部变量和寄存器变量(register variable)都是自动变量。函数的形参及代码块中定义的变量都属于auto变量,这是C语言中应用最广的一种变量,这类变量是栈分配的,是动态分配存储空间的。举函数形参为例,当调用该函数时,为形参分配存储空间,当函数调用结束时,就自动释放这些存储空间。对代码块中定义的变量(包含函数中定义的变量),当执行到变量声明语句时,系统为这些auto变量分配空间,当程序流程离开代码块时,这些变量被自动撤销,其占用的内存空间被释放。

3.堆变量

通过malloc()函数分配内存区域的变量被放在堆中,故称为堆变量。并且似乎这个“堆”和数据结构中的堆没有什么联系,只是一种称呼而已。这种变量需要手动释放内存区域:free(变量名),也就是说它从创建时起就一直存在直到使用free()释放为止。当然,即使最后忘了释放,如今的操作系统也会在程序结束后释放为它分配的内存。不过仍然建议:谁创建,谁释放。

娓娓道来c指针 (2)内存分配

时间: 2024-11-05 12:25:59

娓娓道来c指针 (2)内存分配的相关文章

终于懂了:Delphi的函数名不是地址,取地址必须遵守Object Pascal的语法(Delphi和C的类比:指针、字符串、函数指针、内存分配等)good

这点是与C语言不一样的地方,以前我一直都没有明白这一点,所以总是不明白:函数地址再取地址算怎么回事? ---------------------------------------------------------------------------------------------------------------- 在学习Delphi的时候,一个很好的建议是和C/C++去类比着学习,从指针,到内存管理,到数组,到面向对象……各个方面,都是有很多可以相似和或者也有不同的方,类比着学习,一

指针 && 动态内存分配

C++中的动态内存分配机制 c++中使用new和delete来完成在堆上对动态内存的分配和释放. 注.所有指针都应该被初始化 如果指针指向的动态内存被释放或没有指向合法的地址,就应该将指针设置为nullptr,否则内存泄漏. 变量: double* pvalue {}; pvalue=new double; *pvalue=9.0; 或 double* pvalue {}; pvalue=new double {9.0}; 或合并为一句 double* pvalue {new double{9.

指针以及内存分配

原文:http://blog.csdn.net/bizhu12/article/details/6532235 1. 指针很灵活,这使得指针很难管理,在定义指针时,将在栈中开辟一块内存存放指针的地址(栈内的内存由系统分配和释放),指针的地址内存只是存放指针的地址,不存放指针指向的数据,值得注意的是,定义指针时指针会随机指向一块内存,如int  *p;p会指向一块不为空的内存,相当危险,例如执行判断if(!p){ printf("p为空");};这里不会输出"p为空"

【C++】Geekband-专题二:虚指针和内存分配

1. 传统继承类的设计 static void print_object(const char* name, void* this_, size_t size) { void** ugly = reinterpret_cast<void**>(this_); size_t i; printf("created %s at address %p of size %zu\n", name, this_, size); for(i = 0 ; i < size / size

linux c二级指针的内存分配和使用

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h> int main(int argc, char **argv){    /* 这个是给str分配存储字符串地址的空间 */    char **str = (char**)malloc(sizeof(char*)*256);    /* 这个是给str分配str中的地址所指向的字符串存储空间的大小 */   

golang学习之指针、内存分配

1 func pointer_test() { 2 //空指针,输出为nil 3 var p *int 4 fmt.Printf("p: %v\n", p) 5 //指向局部变量,变量值初始为0 6 var i int 7 p = &i 8 fmt.Printf("p: %v,%v\n", p, *p) 9 //通过指针修改变量数值 10 *p = 8 11 fmt.Printf("p: %v,%v\n", p, *p) 12 //数组的

未解决问题:指针作参数、二重指针、指针数组、动态内存分配

题目:输入m个学生n门课的成绩,计算每个学生的平均成绩,输入学生编号后输出该学生各门课的成绩. 先直接上源码:(有错误的源码) #include <stdio.h> #include <stdlib.h> #include <stdbool.h> int **pointer_counterpart = NULL; int main() { void Input_number(int *m, int *n); //输入m个学生n门课成绩 void allocation(i

c++中函数中变量内存分配以及返回指针、引用类型的思考

众所周知,我们在编程的时候经常会在函数中声明局部变量(包括普通类型的变量.指针.引用等等). 同时,为了满足程序功能的需要,函数的返回值也经常是指针类型或是引用类型,而这返回的指针或是引用也经常指向函数中我们自己声明的局部变量. 这样,程序在某些情况下就可能存在一定的问题.看似很简单的问题,通过仔细的分析,我们就能够更好的理解c++中内存分配和释放的问题. 好,废话不多说,我们进入正题.首先,简单介绍一下程序的内存区域的分配: 程序的内存分配 ①堆区(heap).这一部分主要是由程序开发人员自己

【C/C++学院】0828-数组与指针/内存分配/数据结构数组接口与封装

[送给在路上的程序员] 对于一个开发者而言,能够胜任系统中任意一个模块的开发是其核心价值的体现. 对于一个架构师而言,掌握各种语言的优势并可以运用到系统中,由此简化系统的开发,是其架构生涯的第一步. 对于一个开发团队而言,能在短期内开发出用户满意的软件系统是起核心竞争力的体现. 每一个程序员都不能固步自封,要多接触新的行业,新的技术领域,突破自我. 数组与指针 #include<stdio.h> #include<stdlib.h> void main1() { int a[10]