1、字元陣列和字串
首先區分兩個名詞:字元陣列和字串
字元陣列:首先它是乙個陣列,然後它儲存的元素是字元。如char ch[3]={};
字串:用雙引號包圍的字串行。在c中為了標誌乙個字串的結束,會在字串行的最後乙個字元後新增'\0',以標誌字串的結束。
下面來看具體的例子:
[cpp]view plain
copy
char
ch[3] = ;
char
*p =
"abc"
;
ch[3]是乙個字元陣列,「abc」是乙個字串。他們的長度是不一樣的,ch[3]只有三個元素,而「abc」有四個元素,分別是『a』,'b','c','\0'.
再看乙個例子:
[cpp]view plain
copy
char
ch =
"abc"
;
這時候陣列ch有幾個元素呢?答案是4,因為這裡是用乙個字串來初始化乙個字元陣列,而字串有四個元素,都拷貝到陣列記憶體中,即ch=.
[cpp]view plain
copy
#include
using
namespace
std;
intmain()
;
char
*p =
"abcdefg"
; char
array =
"abcdefg"
; cout<(ch)cout<(p)cout<(array)return
0;
}
ch[3]占用3位元組,這個很顯然。但是p占用4位元組,而array占用8位元組,這是為什麼呢?
這是因為p的型別是char*,也即p是乙個指標變數,指標變數在32位系統中占用4位元組;而array的型別為char[8], 所以會占用8個位元組。
這裡有乙個細節需要注意:"abcdefg"是儲存在靜態常量區。p是棧區的乙個指標,指向該位於靜態常量區的字串;array也是位於棧區,但是用乙個字串常量來初始化乙個棧區的字元陣列,會在棧區開闢一段空間,然後將字串常量拷貝到棧區,所以array就占有8個位元組了,這時候它儲存的只是字串常量的乙個副本,更改array陣列,並不能更改字串常量。示例如下:
[cpp]view plain
copy
#include
using
namespace
std;
intmain()
cout<
cout<
return
0;
}
輸出結果:
abcdefg
abcaefg
另外需要注意的乙個問題是:p指向的是乙個常量區的字串,該字串是不允許被更改,即它是唯讀的。為了防止疏忽,即通過指標p來修改常量,通常將p宣告為const char*.
2、還有乙個特別需要注意的問題:當陣列作為函式的引數時,它又占用多大的記憶體呢?
對於陣列引數,編譯器把它解釋為普通的指標型別,如void fun(char ch[10], char *p),ch的型別是char*,而不是char[10], p的型別是char*,這樣p和ch占用的記憶體都是4個位元組。
下面看一道面試題,練習一下。
[cpp]view plain
copy
char
array =
"abcdefg"
; printf("%d\n"
,sizeof
(array));
// 8
char
ch[7] =
"abcd"
; printf("%d\n"
, sizeof
(ch));
//7char
*p =
"abcdefg"
; printf("%d\n"
,sizeof
(p));
// 4
void
func(
char
p[10])
void
func(
char
(&p)[10])
intmain(
void
)
3、上面所講的其實都是關於sizeof()對於字元相關變數的操作,字元操作還有另乙個常用的函式strlen()
[cpp]view plain
copy
extern
unsigned
intstrlen(
char
*s)
函式求的是字串的實際長度,它求得方法是從開始到遇到第乙個'\0'.
[cpp]view plain
copy
#include
using
namespace
std;
intmain()
;
char
str2[10] = ;
char
str3[10] =
"abc"
; char
str4 =
"abc"
; char
*str5 =
"abc"
; coutcoutcoutcoutcoutreturn
0; }
變數名稱的後面部分比前面部分具有更強的約束力。
所以,如下變數宣告:
int **a[3][6];
cout<<"a="<
表示「int **」
型別的二維陣列(「」比
「int」
和「*」
更具有約束力)。這個二維陣列共有
18個成員(
3×6),每個成員是乙個指標(
int **
),每個指標的長度是
4(如果是
32位計算機,其他位計算機可以類推)。所以,這個陣列的長度為:
18 × 4 =72
。 首先要說明的
int **a[3][6]
的意思是定義一組指向指標變數的二維指標陣列,
也就是說,定義了乙個3行
6列的指標陣列,每個指標都指向乙個指標,
從儲存結構上來說,就是乙個儲存了
18個指標變數的陣列,
這裡的a
指的到底是什麼,a
本身實際含義是乙個位址,表示
a[3][6]
這個陣列的首位址,就a
作為乙個個位址來說,它占用
4個位元組;同時a
也是a[3][6]
這個陣列一種表示
,如果用
sizeof(a)
去求解的話
,它代表的是
a[3][6]
這個陣列所占用的空間
,而不是
a這乙個位址所占用的儲存空間
,也就是
18個指標變數所佔的空間
,自然是
72個位元組了.
經典問題:
double* (*a)[3][6];
coutcout<*a為乙個有3*6個指標元素的陣列
cout<**a為陣列一維的6個指標
cout<***a為一維的第乙個指標
cout<****a為乙個double變數
問題解析:
a 是乙個很奇怪的定義,他表示乙個指向
double*[3][6]
型別陣列的指標。既然是指標,所以
sizeof(a)就是4
。
既然a是執行
double*[3][6]
型別的指標,
*a就表示乙個
double*[3][6]
的多維陣列型別,因此
sizeof(*a)=3*6*sizeof(double*)=72
。同樣的,
**a表示乙個
double*[6]
型別的陣列,所以
sizeof(**a)=6*sizeof (double*)=24
。***a
就表示其中的乙個元素,也就是
double*
了,所以
sizeof(***a)=4
。至於****a
,就是乙個
double
了,所以
sizeof(****a)=sizeof(double)=8
。
sizeof用法總結
在vc中,sizeof有著許多的用法,而且很容易引起一些錯誤。下面根據sizeof後面的 引數對sizeof的用法做個總結。a 引數為資料型別或者為一般變數。例如sizeof int sizeof long 等等。這種情 況要注意的是不同系統系統或者不同編譯器得到的結果可能是不同的。例如int型別在...
sizeof 用法總結
sizeof 功能 計算資料空間的位元組數 1.與strlen 比較 strlen 計算字元陣列的字元數,以 0 為結束判斷。而sizeof計算資料 包括陣列 變數 型別 結構體等 所佔記憶體空間,用位元組數表示 2.指標與靜態陣列的sizeof操作 指標均可看為變數型別的一種。所有指標變數的siz...
sizeof用法總結
sizeof用法總結 以下執行環境都是一般的,在32位編譯環境中 1,基本資料型別的sizeof cout 再看示例 pragma pack push 將當前pack設定壓棧儲存 pragma pack 2 必須在結構體定義之前使用 struct s1 struct s3 pragma pack p...