1. 程式人生 > >C/C++中字元指標和字元陣列、字元指標陣列及指向指標的指標的含義

C/C++中字元指標和字元陣列、字元指標陣列及指向指標的指標的含義

字元指標和字元陣列

char* s1="hello";

char  s2[]="world";
兩個表示式的含義是一樣的.
如果講不同之處的話,VC6中編譯時,對這兩種定義進行了不同的處理;
char *s1 = "hello"; 中的"hello",編譯時指標指向的區域位於PE檔案的.rdata節中,是隻讀的.
不信的話,你可以試試:

main()
{
  char *s1="hello";
  char s2[]="world";

  *(s2+2)='x'; //正確
  *(s1+2)='x'; //執行時出錯.
}

1.嚴格的說兩個表達的意思是不完全一樣的,因為前者是個字串指標,這個指標S1所存的地址就是儲存字串前8個位元組即hello/n/n/n的那個地址。
  2.而後者是字元陣列。每個字元都有一個獨立的地址。
見圖示。

 

字元指標陣列及指向指標的指標的含義

#include <iostream
#include <string
using namespace std; 
 
void print_char(char* array[],int len);//函式原形宣告 
 
void main(void)   

//-----------------------------段1----------------------------------------- 
    char *a[]={"abc","cde","fgh"};//字元指標陣列 
    char* *b=a;//定義一個指向指標的指標,並賦予指標陣列首地址所指向的第一個字串的地址也就是abc/0字串的首地址 


    cout<<*b<<"|"<<*(b+1)<<"|"<<*(b+2)<<endl; 
//------------------------------------------------------------------------- 
 
//-----------------------------段2----------------------------------------- 
    char* test[]={"abc","cde","fgh"};//注意這裡是引號,表示是字串,以後的地址每加1就是加4位(在32位系統上) 

    int num=sizeof(test)/sizeof(char*);//計算字串個數 
    print_char(test,num); 
    cin.get(); 
//------------------------------------------------------------------------- 

 
void print_char(char* array[],int len)//當呼叫的時候傳遞進來的不是陣列,而是字元指標他每加1也就是加上sizeof(char*)的長度 

    for(int i=0;i<len;i++) 
    { 
        cout<<*array++<<endl; 
    } 
}

  下面我們來仔細說明一下字元指標陣列和指向指標的指標,段1中的程式是下面的樣子:

char *a[]={"abc","cde","fgh"}; 
char* *b=a; 
cout<<*b<<"|"<<*(b+1)<<"|"<<*(b+2)<<endl;

  char *a[]定義了一個指標陣列,注意不是char[], char[]是不能同時初始化為三個字元的,定義以後的a[]其實內部有三個記憶體位置,分別儲存了abc/0,cde/0,fgh/0,三個字串的起始地址,而這三個位置的記憶體地址卻不是這三個字串的起始地址,在這個例子中a[]是儲存在棧空間內的,而三個字串卻是儲存在靜態記憶體空間內的const區域中的,接下去我們看到了char* *b=a;這裡是定義了一個指向指標的指標,如果你寫成char *b=a;那麼是錯誤的,因為編譯器會返回一個無法將char* *[3]轉換給char *的錯誤,b=a的賦值,實際上是把a的首地址賦給了b,由於b是一個指向指標的指標,程式的輸出cout<<*b<<"|"<<*(b+1)<<"|"<<*(b+2)<<endl;

  結果是

abc
cde
fgh

  可以看出每一次記憶體地址的+1操作事實上是一次加sizeof(char*)的操作,我們在32位的系統中sizeof(char*)的長度是4,所以每加1也就是+4,實際上是*a[]內部三個位置的+1,所以*(b+1)的結果自然就是cde了,我們這時候可能會問,為什麼輸出是cde而不是c一個呢?答案是這樣的,在c++中,輸出字元指標就是輸出字串,程式會自動在遇到/0後停止.

  我們最後分析一下段2中的程式碼,段2中我們呼叫了print_array()這個函式,這個函式中形式引數是char *array[]和程式碼中的char *test[]一樣,同為字元指標,當你把引數傳遞過來的時候,事實上不是把陣列內容傳遞過來,test的首地址傳遞了進來,由於array是指標,所以在記憶體中它在棧區,具有變數一樣的性質,可以為左值,所以我們輸出寫成了,cout<<*array++<<endl;當然我們也可以改寫為cout<<array[i]<<endl,這裡在迴圈中的每次加1操作和段1程式碼總的道理是一樣!

相關推薦

C/C++字元指標字元陣列字元指標陣列指向指標指標含義

字元指標和字元陣列 char* s1="hello"; char  s2[]="world";兩個表示式的含義是一樣的.如果講不同之處的話,VC6中編譯時,對這兩種定義進行了不同的處理;char *s1 = "hello"; 中的"hello",編譯時指標指向的區域位於PE

C語言的字串字元陣列

本文來源於網路,轉載為是了更好的複習! 原文網址 :點這裡 1、字元陣列的定義與初始化 字元陣列的初始化,最容易理解的方式就是逐個字元賦給陣列中各元素。 char str[10]={ 'I',' ','a','m',' ',‘h','a','p','p','y'}; 即把1

c/c++ 字元陣列字元指標字串型別

一、字元陣列 定義:用來存放字元資料的陣列是字元陣列,字元陣列中的一個元素存放一個字元。字元陣列具有陣列的共同屬性。 初始化方式: 1 charc[10]={'0','1','2','3','4','5','6','7','8','9'}; 注:當初值個數小於規定長度

C語言-陣列字元指標陣列函式介面與使用

#include <stdio.h> #include <stdlib.h> typedef char* myString; //#define MY_STRING #if

解決C++連線MySQL資料庫插入獲取記錄中文字元亂碼問題

字元編碼真是個頭痛的問題,以前一直不放在心上,現在用到了才發現真的麻煩。 花了將近一天的時間終於達到目的。 測試環境VS2015+MYSQL5.5,各種編碼的具體說明就不講了,自行百度。 1、讀取資料亂碼問題: vs專案下,預設編碼Unicode,但我的資料庫預設utf

c語言統計輸入的行數單詞數與字元

來源:《c程式設計語言》 功能需求: 寫個函式,用於統計輸入的行數、單詞數與字元數。這裡對單詞的定義比較寬鬆,它是任何其中不包含空格、製表符或換行符的字元序列。 程式碼如下: #include <stdio.h> #define IN 1 #define OUT 0 void wc()

C++類成員變數成員指標變數小結

指標的確有點難理解,不過它之所以存在並大範圍使用,這樣做是有一定道理的。 一、C++中的類和結構使用指標定義成員作用 1、多型的要求。 如果要使用同一介面,多型設計,那麼就一定要使用基類指標。只有指標才能在實力化後動態的判斷使用哪個方法。2、程式碼複用。有一些程式要設計

C語言的一個*[]優先級問題

pre 執行 return ges spa 技術 分享 malloc bsp 最近寫著玩了這麽一段代碼 1 int Init(int **T, int v1, int v2, int v3) 2 { 3 4 if (!(*T=(int*) malloc(3*

c語言宏定義常量定義的區別

沒有 int 符號表 cnblogs 格式 nbsp 參數 不同之處 區別   他們有共同的好處就是“一改全改,避免輸入錯誤”哪兩者有不同之處嗎?有的。   主要區別就在於,宏定義是在編譯之前進行的,而const是在編譯階段處理的 宏定義不占用內存單元而const定義的常量

C語言】一維陣列二維陣列指標

一維陣列和指標: 1、一維陣列名: 對於這樣的一維陣列:int a[4];  a作為陣列名就是我們陣列的首地址, a是一個地址常量 .  首先說說常量和變數的關係, 對於變數來說, 用箱子去比喻再好不過了, 宣告一個變數就宣告一個箱子,比如我們開闢出一個蘋果型別的箱子, 給這個變

java新手:字串陣列字元陣列字串之間的轉換

(1)字串和字元陣列的轉化 // 字串轉化成字元陣列 String str = "abcdefg"; char[] ch = str.toCharArray(); //輸出a System.out.println(ch[0]); //字元陣列

C++模板的省略號可變引數模板

#include <iostream> using namespace std; void print() { cout << "hello world" << endl; } template<class T> voi

C語言巨集定義函式的取捨

原文連結:http://www.embedu.org/Column/Column177.htm 要寫好C語言,漂亮的巨集定義是非常重要的。巨集定義可以幫助我們防止出錯,提高程式碼的可移植性和可讀性等。 在軟體開發過程中,經常有一些常用或者通用的功能或者程式碼段,這些功能既可以寫成函式,也可以

c語言的 strcpystrncpy字串函式使用介紹

1.strcpy函式 函式原型:char *strcpy(char *dst,char const *src)            必須保證dst字元的空間足以儲存src字元,否則多餘的字元仍然被複制,覆蓋原先儲存在陣列後面的記憶體空間的數值,strcpy無法判斷這個問題因為他無法判斷字元陣列的長度。

java String與包裝類位元組陣列字元陣列間的轉換

java String與包裝類和位元組陣列、字元陣列間的轉換 1. 字串與基本資料的相互轉化 2.字串與字元、位元組陣列之間的轉換 1.字串轉換成字元陣列 2. 位元組陣列轉換成字串

c++模板的 typename class

在c++Template中很多地方都用到了typename與class這兩個關鍵字,而且在泛型程式設計的時候可以替換,但是 typename 和 class 並不是完全一致的。 相信學習C++的人對class這個關鍵字都非常明白,class用於定義類,在模板引入c++後,最初定義模板的方法

C的介面繼承多型

 上一節中我們學習到了建構函式,用來初始化一個物件的例項。同時在.NET Framework中,提供了解構函式用於清理物件。一般情況下不需要特別解構函式,系統會自動提供預設的解構函式來執行操作,清理不再需要的物件。 一、 靜態和例項類成員 屬性,方法和欄位等成員是物件例項所

詳解C語言的 %*s %.*s

%*s:取決於在scanf中使用還是在printf中使用。 1.在scanf中使用,則添加了*的部分會被忽略,不會被引數獲取。 例如: int a,b; char b[10]; scanf("%d%*s",&a,b); //輸入為:12 abc那麼12將會讀取到變數a

c語言的__FILE____LINE__的作用

這是編譯器內建巨集,這些巨集定義不僅可以幫助我們完成跨平臺的原始碼編寫,靈活使用也可以巧妙地幫我們輸出非常有用的除錯資訊。 例如:printf("FILE: %d, LINE: %d, %s/n", "__FILE__, __LINE__, "這裡寫上相關資訊"); ANS

C語言區域性變數全域性變數變數的儲存類別(static,extern,auto,register)

C語言中區域性變數和全域性變數變數的儲存類別(static,extern,auto,register) 1----區域性變數和全域性變數 在討論函式的形參變數時曾經提到,形參變數只在被呼叫期間才分配記憶體單元,呼叫結束立即釋放。這一點表明形參變數只有在函式內才是有效的,離開該函式就不能再使用了。