1. 程式人生 > >對使用字符指針變量和字符數組的討論

對使用字符指針變量和字符數組的討論

tac strcpy 賦值 int void 編譯器 heap 很大的 對數

區別:1、字符數組由若幹個元素組成,每個元素中放一個字符,而字符指針變量中存放的是地址(字符串第一個字符的地址)。

2、賦值方式。對字符數組只能對各個元素賦值,不能用以下方法對字符數組賦值:char str[20]; str="I love China";而對字符指針變量,可以用如下方法賦值:char *a; a="I love China ";註意,賦值給a的不是字符,而是字符串的第一個元素的地址。

3、對字符指針變量賦初值:char *a="I love China";等價於char*a; a="I love China";而對數組的初始化:char a[20]={"I love China"};不能等價於:char str[20];str[]="I love China";

4、如果定義了一個字符數組,在編譯時為它們分配內存單元,它有確定的地址。而定義一個字符指針變量時,給指針變量分配內存單元,在其中可放一個字符指針變量的地址。也就是說,該指針變量可以指向一個字符型數據,但若未對它賦予一個地址值,則它未具體指向一個確定的字符數據。例:char str[10]; sanf("%s",str); 合法。但:char *a; scanf("%s",a); 有時也可執行,但風險較大。

5、指針變量的值是可以改變的,例:

#include <stdafx.h>
#include<stdio.h>

void main()
{
    char *a="
Hello word"; a+=4; printf("%s\n",a); }

註:指針變量的值(即地址)可以改變,但指針指向的值無法改變。

6、若定義了一個指針變量,並使它指向一個字符串,就可以用下標形式引用指針變量所指的字符串中的字符。

例:

 1 #include <stdafx.h>
 2 #include<stdio.h>
 3 
 4 void main()
 5 {
 6     char *a="Hello word";
 7     int i=0;
 8     for(;a[i]!=\0;i++)
 9     {printf("
%c",a[i]); 10 } 11 }

7、在內存中的儲存位置不同。

例:

#include <stdafx.h>
#include<stdio.h>

void main()
{
    void copy_string(char*from,char*to);
    char*a="Hello word";
    char*b="I love China";
    printf("%s\n%s\n",a,b);
    copy_string(a,b);
    printf("%s\n%s\n",a,b);
}
void copy_string(char*from,char*to)
{
    for(;*from!=\0;from++,to++;)
    {
        *to=*from;
    }
    *to=\0;
}

會出錯,

程序中的”I love China”字符串在常量區,而使用指針存放字符串,b中只是存放了字符串在常量區中的地址,當調用copy_string函數的時候又引用了b這個參數,即試圖將字符串”I am a teacher.”寫入常量區。而常量區的這段內存是不可寫的,所以在運行的時候出現了報錯。 對這段代碼的改進只許把b改為用數組來存放字符串(對a不必修改,因為程序中沒有執行對a寫入的操作)。 char *b = "You are a student."; 改為 char b[] = "You are a student."; 一般認為在c中分為這幾個存儲區: 1. 棧 --有編譯器自動分配釋放 2. 堆 -- 一般由程序員分配釋放,若程序員不釋放,程序結束時可能由OS回收 3. 全局區(靜態區) -- 全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域,未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域。程序結束釋放。 4. 另外還有一個專門放常量的地方。程序結束釋放 在函數體中定義的變量通常是在棧上,用malloc, calloc, realloc等分配內存的函數分配得到的就是在堆上。在所有函數體外定義的是全局量,加了static修飾符後不管在哪裏都存放在全局區(靜態區),在所有函數體外定義的static變量表示在該文件中有效,不能extern到別的文件用,在函數體內定義的static表示只在該函數體內有效。另外,函數中的"adgfdf"這樣的字符串存放在常量區。 比如:
 1 int a = 0; //全局初始化區 
 2 char *p1; //全局未初始化區
 3 main() {    int b; //
 4 char s[] = "abc"; //
 5 char *p2; //
 6 char *p3 = "123456"; //123456\0在常量區,p3在棧上。    
 7 static int c = 0//全局(靜態)初始化區    
 8     p1 = (char *)malloc(10);   
 9 p2 = (char *)malloc(20);    //分配得來得10和20字節的區域就在堆區。    
10 strcpy(p1, "123456");    //123456\0放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一塊。 }

還有就是函數調用時會在棧上有一系列的保留現場及傳遞參數的操作。 棧的空間大小有限定,vc的缺省是2M。棧不夠用的情況一般是程序中分配了大量數組和遞歸函數層次太深。有一點必須知道,當一個函數調用完返回後它會釋放該函數中所有的棧空間。棧是由編譯器自動管理的,不用你操心。 堆是動態分配內存的,並且你可以分配使用很大的內存。但是用不好會產生內存泄漏。並且頻繁地malloc和free會產生內存碎片(有點類似磁盤碎片),因為c分配動態內存時是尋找匹配的內存的。而用棧則不會產生碎片。 在棧上存取數據比通過指針在堆上存取數據快些。 一般大家說的堆棧和棧是一樣的,就是棧(stack),而說堆時才是堆heap. 棧是先入後出的,一般是由高地址向低地址生長。

對使用字符指針變量和字符數組的討論