`

字符串指针和字符数组,静态全局、静态局部、全局和局部变量区别,字符串常量和字符串变量,程序的内存分配

 
阅读更多
最近工作之余,发现了两个自己在C语言学习中的难点,一个是字符串指针和字符数组的区别,一个就是静态全局变量、静态局部变量、全局变量和局部变量的区别,在网上查了不少资料,收获良多,现在与大家分享,有错误的地方请大家指正! 
以下程序用VC++6.0调试 
先说说字符串指针和字符数组的区别 1. 相同点: 
/*  用字符数组实现字符串操作 */ main( )  {  
char str[]="Welcome to study C !";    int i; 
printf("%s\n",str);    for (i=0;i<=7;i++)         
printf("%c",str[i]);  //用*(str+i)也行  printf("\n");  }  
 
/*  用字符指针实现字符串操作  */ main()  { 
char *str="Welcome to study C !"; int i; 
printf("%s\n",str);   for(i=0;i<=7;i++)   
printf("%c",*(str+i)); //用str[i]也行 printf("\n"); } 
 
2. 不同点: 
a) 赋值方式不同,字符数组只能对各个元素分别赋值,而字符指针只需赋给字符串的
首地址就可以了。 如:  char *str; 
        str="Welcome to study C !"; 
以下对字符数组的赋值是错误的: 
        char str[80]; 
        str[ ]="Welcome to study C !"; 
b) 字符指针指向字符串,"hello"是一个字符串常量,与之相关联的内存空间位于内
存的只读部分,如: 
  char ch[] = "china\n";   char *p;   char *pp = "CHINA\n";   p = ch;   *(p+2) = 'h';//就是可以的   *(pp+2) = 'h';//此处在编译时不会出错,在执行的时候会出错 






 
c)   函数参数列表中的以数组类型书写的形式参数,编译器把其解释为普通的指针类型,
对于void func (char sa[100],int ia[20],char *p),则sa的类型为char*,而不是char[100]类型  
下面介绍一下字符串常量和字符串变量:  
1.  字符串常量: 
a) 定义:是一对双引号括起来的字符序列 
b) 字符串包含的字符个数:不包括系统自动赋的’\0’,转义字符算1个 c) 所占的字节数:字符串所包含的字符个数加1 
d) 长度:从第一个字符到第一个’\0’之间的字符个数,哪怕’\0’就在原字符串中 e) 无论字符串常量还是字符串变量,空字符串可以存在””,而空字符是错误的’’ 2.  字符串变量: 
a) C语言本身没有设置一种类型来定义字符串变量,字符串的存储完全依赖于字符数
组,但字符数组又不等于是字符串变量,例如: Char str[] = {‘a’,’b’,’c’,’\0’};是str[4],是字符串 Char str[] = {‘a’,’b’,’c’};是str[3],是字符数组 Char str[7] = “string!”;可能破坏其他数据 
b) 在scanf,printf,gets,puts中的str不用写成str[10],只能写成str  
下面介绍下静态全局变量,静态局部变量,全局变量,局部变量的区别    
1. 从作用域看:全局变量具有全局作用域。全局变量只需在一个源文件中定义,就可以作
用于所有的源文件。当然,其他不包含全局变量定义的源文件需要用 extern 关键字再次声明这个全局变量。 
2. 静态局部变量具有局部作用域,它只被初始化一次,自从第一次被初始化直到程序运行
结束都一直存在,它和全局变量的区别在于全局变量对所有的函数都是可见的,而静态局部变量只对定义自己的函数体始终可见。 
3. 静态全局变量也具有全局作用域,它与全局变量的区别在于如果程序包含多个文件的话,
它作用于定义它的文件里,不能作用到其它文件里,即被 static 关键字修饰过的变量具有文件作用域。这样即使两个不同的源文件都定义了相同名字的静态全局变量,它们也是不同的变量。 4. 从分配内存空间看:全局变量,静态局部变量,静态全局变量都在静态存储区分配空间,
而局部变量在栈里分配空间。(扩展内存分配) 
5. 把局部变量改变为静态变量后是改变了它的存储方式即增加了它的生存期。把全局变量
改变为静态变量后是改变了它的作用域,限制了它的使用范围。  
程序的内存分配  
1. 程序占用的内存分为以下几个部分 
a) 栈区(stack):由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。
其操作方式类似于数据结构中的栈。 b) 堆区(heap):一般由程序员分配释放,若程序员不释放,程序结束时可能由OS
回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。 






 
c) 全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的
全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后由系统释放。 
d) 文字常量区:常量字符串就是放在这里的。 程序结束后由系统释放 e) 程序代码区:存放函数体的二进制代码。 2. 例子程序   
//main.cpp   
int a = 0; 全局初始化区   char *p1; 全局未初始化区   main()   {   
int b; 栈   
char s[] = "abc"; 栈   char *p2; 栈   
char *p3 = "123456"; 123456\0在常量区,p3在栈上。   static int c =0; 全局(静态)初始化区   p1 = (char *)malloc(10);   p2 = (char *)malloc(20);   
分配得来得10和20字节的区域就在堆区。   
strcpy(p1, "123456"); 123456\0放在常量区,编译器可能会将它与p3所指向的"123456" 优化成一个地方。   }   因此 static 这个说明符在不同的地方所起的作用是不同的。 若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度;  
若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度;   
设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题,因为他们都放在静态数据存储区,全局可见;  
如果我们需要一个可重入的函数,那么,我们一定要避免函数中使用 static 变量(这样的函数被称为:带“内部存储器”功能的的函数)    
函数中必须要使用static 变量情况:比如当某函数的返回值为指针类型时,则必须是static 的局部变量的地址作为返回值,若为auto类型,则返回为错指针。  
static 全局变量:改变作用范围,不改变存储位置;static 局部变量:改变存储位置,不改变作用范围;静态函数 :在函数的返回类型前加上static 关键字,函数即被定义为静态函数,只能在声明它的文件当中可见,不能被其它文件使用。 初始化 
如果括号中提供的处置个数大于数组长度,则会出错。如果初值小于数组长度,则将字符赋值给数组中前面的对应元素,其余元素自动填充空字符‘\0’。 
格式化输出字符串时,输出项是字符数组名,不能写成数组中的元素。 输入函数的输入项直接写数组名,不写地址符&。 输入函数遇到空格认为结束。 两个字符数组变量不能直接赋值,只能通过移动下标操作字符数组中的每个元素进行分别赋值;两个字符值指针,可以直接赋值,即把一个字符指针所指向的地址赋值给另一个指针,






 
则两个指针指向的同一个地址。字符数组和字符串两者之间不能直接赋值。    
严格的说两个表达的意思是不完全一样的,因为前者是个字符串指针,这个指针S1所存的地址就是存储字符串前8个字节即hello/n/n/n的那个地址。 而后者是字符数组。每个字符都有一个独立的地址。 见图示。 
字符串变量:在c中是没有这个概念的,c中如果想将一个字符串存放到变量中,必须使用字符数组,就是用一个字符型数组存放一个字符串,一些自己的保护代码,通过软件手段将这段内存软保护起来。这种保护在汇编级别可以轻松突破,其保护也就无效了。 
转自http://wenku.baidu.com/view/448352f9910ef12d2af9e70c.html
分享到:
评论

相关推荐

    全局变量、局部变量、静态变量即内存管理

    从分配内存空间看,全局变量,静态局部变量,静态全局变量都在静态存储区分配空间,而局部变量在栈里分配空间。从以上分析可以看出,把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量...

    C语言-字符串常量(超详细)

    2. 全局区(Global Segment):存放全局变量、静态变量和常量,包括字符串常量。 3. 栈区(Stack Segment):存放函数的参数值、返回值、局部变量等,自动分配和释放。 4. 堆区(Heap Segment):用于动态内存分配,...

    局部变量 全局变量 堆栈总结

    字符串常量(如 `"abcdef"`)通常存储在文字常量区,这部分内存区域是只读的,不能被修改。这意味着如果试图修改字符串常量的内容会导致未定义行为。 #### 七、总结 在程序设计中,正确理解局部变量、全局变量、堆...

    全局变量和局部变量在内存里的区别[借鉴].pdf

    全局变量和局部变量在内存管理上有显著的区别,这主要体现在它们的存储区域、生命周期和作用域上。在C/C++编程中,程序的内存被划分为五个主要区域: 1. **栈区(Stack)**:栈是用于存放函数参数、局部变量的地方...

    C++堆栈自由存储区全局静态存储区和常量存储区 C++堆栈自由存储区全局静态存储区和常量存储区

    全局静态存储区用于存放全局变量和静态局部变量。这类变量的特点在于: 1. **生命周期**:在整个程序执行期间都存在,不会随着函数的结束而消失。 2. **初始化**:在程序启动时就完成了初始化。 3. **存储位置**:...

    PHP static局部静态变量和全局静态变量总结

    PHP中静态变量分为局部静态变量和全局静态变量,它们都有存储状态的特性,但使用场景和初始化规则有所不同。在编程中,合理地利用静态变量,可以有效管理函数内部数据的持久化状态和程序的全局状态。 局部静态变量...

    内存的堆分配和栈分配&字符数组,字符指针,Sizeof总结[参考].pdf

    在`main`函数内部,`int b`、`char s[]`和`char *p2`都在栈上,`char *p3`指向的字符串常量在文字常量区,`static int c`属于全局(静态)初始化区。`p1`和`p2`指向的内存是在堆区通过`malloc`分配的。 3. **堆和栈...

    C++堆栈自由存储区全局静态存储区和常量存储区

    常量存储区专门用来存放程序中的常量,比如字符串常量。其特点如下: - **不可修改**:一旦写入,就不能再修改。 - **生命周期**:整个程序运行期间都存在。 - **优化**:对于相同的常量,编译器可能只保留一份副本...

    谭浩强C程序设计第三版

    字符串常量 48 变量赋初值 48 各类数值型数据之间的混合运算 49 算术运算符和算术表达式 51 C运算符简介 51 算术运算符和算术表达式 51 赋值运算符和赋值表达式 53 逗号运算符和逗号表达式 55 小结 55 C的数据类型 ...

    C语言程序设计(谭浩强)第三版

     8.4.3使用字符指针变量和字符数组的比较  8.5指向函数的指针  8.5.1什么是函数指针  8.5.2用函数指针变量调用函数  8.5.3怎样定义和使用指向函数的指针变量  8.5.4用指向函数的指针作函数参数  8.6返回指针...

    完整版C语言程序设计TXT电子书

    3.5.5 字符串常量 41 3.5.6 符号常量 42 3.6 变量赋初值 42 3.7 各类数值型数据之间的混合运算 43 3.8 算术运算符和算术表达式 44 3.8.1 C运算符简介 44 3.8.2 算术运算符和算术表达式 45 3.9 赋值...

    C语言程序设计标准教程

     本程序中用赋值语句给num和name两个成员赋值,name是一个字符串指针变量。用scanf函数动态地输入sex和score成员值,然后把boy1的所有成员的值整体赋予boy2。最后分别输出boy2 的各个成员值。本例表示了结构变量的...

    聊聊 C 语言的内存模型与指针

    全局变量和静态变量(包括静态局部变量)根据是否初始化被分配到相邻的区域,初始化的数据通常存储在一块,未初始化的数据存储在另一块。字符串常量和一般常量通常存储在程序的只读数据段中。 栈区用于存放函数的...

    C++程序设计学习笔记.pdf

    字符串在C++中分为字符数组和字符串常量,它们在内存中存储位置不同,字符串比较通常用`strcmp()`函数。C++标准库提供`string`类型,支持更多的操作。 指针数组是一个数组,其中每个元素都是一个指针。传递数组给...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar )

    3.5.5 字符串常量 41 3.5.6 符号常量 42 3.6 变量赋初值 42 3.7 各类数值型数据之间的混合运算 43 3.8 算术运算符和算术表达式 44 3.8.1 C运算符简介 44 3.8.2 算术运算符和算术表达式 45 3.9 赋值运算符和赋值...

    《C语言程序设计》谭浩强

    3.5.5 字符串常量 41 3.5.6 符号常量 42 3.6 变量赋初值 42 3.7 各类数值型数据之间的混合运算 43 3.8 算术运算符和算术表达式 44 3.8.1 C运算符简介 44 3.8.2 算术运算符和算术表达式 45 3.9 赋值运算符和赋值...

    探讨:程序在内存中的分配(常量,局部变量,全局变量,程序代码)问题

    4. **常量区**:存储程序中的常量,如字符串字面量 `"123456"` 和 `"123456\0"`。常量不允许被程序修改。 在C++中,内存分配增加了两个额外的概念: 5. **自由存储区(Free Store)**:这是与堆类似的概念,指的是...

    谭浩强c语言程序设计

    3.5.5 字符串常量 41 3.5.6 符号常量 42 3.6 变量赋初值 42 3.7 各类数值型数据之间的混合运算 43 3.8 算术运算符和算术表达式 44 3.8.1 C运算符简介 44 3.8.2 算术运算符和算术表达式 45 3.9 赋值运算符和赋值...

    谭浩强 C语言程序设计 教程全书 Word版

    3.5.5 字符串常量 11 3.5.6 符号常量 12 3.6 变量赋初值 12 3.7 各类数值型数据之间的混合运算 13 3.8 算术运算符和算术表达式 14 3.8.1 C运算符简介 14 3.8.2 算术运算符和算术表达式 15 3.9 赋值运算符和赋值...

    DSP程序变量存储问题

    - `.const`:存储字符串常量和由`const`关键字初始化的全局变量及静态变量。 - `.econst`:类似于`.const`段,但存储的是由`farconst`关键字初始化的数据。 - `.pinit`:存放C++全局构造器程序列表。 - `.switch...

Global site tag (gtag.js) - Google Analytics