字符數組,字符指針,sizeof,strlen總結


先看下面這一段代碼,讀者可以自己思考一下,是否自己可以完全答對

// test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include<cstdio>
#include <string>
using namespace std;


struct{
	short a1;
	short a2;
	short a3;
}A;
	
struct{
	long b1;
	short b2;
}B;

int _tmain(int argc, _TCHAR* argv[])
{
	char *ss1="0123456789";
	cout<<"sizeof(ss1)="<<sizeof(ss1)<<endl;  //4
	cout<<"sizeof(*ss1)="<<sizeof(*ss1)<<endl; //1
	cout<<"slrlen(ss1)="<<strlen(ss1)<<endl;   //10

	char ss2[]="0123456789";
	cout<<"sizeof(ss2)="<<sizeof(ss2)<<endl; //11
	cout<<"sizeof(*ss2)="<<sizeof(*ss2)<<endl; //1
	cout<<"slrlen(ss2)="<<strlen(ss2)<<endl;   //10

	char ss3[100]="0123456789";
	cout<<"sizeof(ss3)="<<sizeof(ss3)<<endl; //100
	cout<<"slrlen(ss3)="<<strlen(ss3)<<endl;   //10

	int ss4[100];
	cout<<"sizeof(ss4)="<<sizeof(ss4)<<endl; //400
	//cout<<"slrlen(ss4)="<<strlen(ss4)<<endl;  //Error noly char * and endswith '\0'

	char q1[]="abc";
	cout<<"sizeof(q1)="<<sizeof(q1)<<endl; //4

	char q2[]="abc\n";
	cout<<"sizeof(q2)="<<sizeof(q2)<<endl; //5

	char *q3="abc\n";
	cout<<"sizeof(q3)="<<sizeof(q3)<<endl; //4

	char* str1=(char*)malloc(100);
	cout<<"sizeof(str1)="<<sizeof(str1)<<endl; //4

	void *str2=(void*)malloc(100);
	cout<<"sizeof(str2)="<<sizeof(str2)<<endl; //4

	cout<<"sizeof(A)="<<sizeof(A)<<endl;  //6
	cout<<"sizeof(B)="<<sizeof(B)<<endl;  //8

	return 0;

}

image

下面我們來總結一下吧:

對於字符數組與字符指針:

1. 以字符串形式出現的,編譯器都會為該字符串自動添加一個0作為結束符,如在代碼中寫"abc",那么編譯器幫你存儲的是"abc\0".

2. 字符串直接量作為字符指針的初始值

  "hello"是一個字符串直接量,編譯器將其作為const char*處理,與之相關聯的內存空間位於內存的只讀部分,即允許編譯器重用指向等價字符串直接量的引用以優化內存使用,

即使程序  中使用了字符串直接量500次,編譯器在內存中也只是創建了一個實例。例如: char *ptr = “hello”; 等價於 const char *ptr = “hello”;

字符串直接量"hello"關聯的是只讀內存,如果試圖修改將出錯,例如ptr[1] = ‘a’;是會引起錯誤的。

3. 字符串直接量作為基於棧的字符數組的初始值

    由於基於棧的變量不可能引用其他地方存儲的內存,編譯器會負責將字符串直接量復制到基於棧的數組內存中。

    例如: char stackArray[] = “hello”;

    做如下修改: stackArray[1] = ‘a’;是真確的。

4. 字符數組與字符指針

   字符數組的形式如下,會將字符直接量拷貝到棧上:

          char str[]   = "abc";             // 實際的數據存儲: a b c \0,也就是增加了一個終結符\0

          char str[3] = {'a','b','c'};     // 實際的數據存儲: a b c,並沒有在最后添加終結符

          char str[10] = {'a','b','c'};   // 實際的數據存儲: a b c \0 \0 \0 \0 \0 \0 \0

   字符指針的形式如下:

          char *str = “abc”;               // 實際的數據存儲: a b c \0,也就是增加了一個終結符\0

5. 類型的決定

    1). 數組的類型是由該數組所存放元素的類型以及數組本身的大小決定的

         如char s1[3]和char s2[4],s1的類型就是char[3],s2的類型就是char[4],也就是說盡管s1和s2都是字符數組,但兩者的類型卻是不同的。

    2). 字符串常量的類型可以理解為相應字符常量數組的類型

         如"abcdef"的類型就可以看成是const char[7],也就是說實際的數據存儲為"abcdef\0"。

    3). 函數參數列表中的以數組類型書寫的形式參數,編譯器把其解釋為普通的指針類型

         如對於void func(char sa[100],int ia[20],char *p),則sa的類型為char*,ia的類型為int*,p的類型為char*。

對於sizeof與strlen:

1. sizeof操作符的結果類型是size_t,它在頭文件中typedef為unsigned int類型。該類型保證能容納實現所建立的最大對象的字節大小。

2. sizeof是算符,strlen是函數。

3. sizeof可以用類型做參數,strlen只能用char*做參數,且必須是以''\0''結尾的。

4. 數組做sizeof的參數不退化,傳遞給strlen就退化為指針了。

5. 大部分編譯程序在編譯的時候就把sizeof計算過了,是類型或是變量的長度這就是sizeof(x)可以用來定義數組維數的原因。
    char str[20]="0123456789"; // str是編譯期大小已經固定的數組
     int a=strlen(str); //  a=10; //strlen()在運行起確定,計算的是實際長度
     int b=sizeof(str); //  而b=20; //sizeof()在編譯期確定,str的類型是int[20],計算的是占據內存的大小

6. strlen的結果要在運行的時候才能計算出來,是用來計算字符串的實際長度,不是類型占內存的大小。

7. sizeof后如果是類型必須加括弧,如果是變量名可以不加括弧。這是因為sizeof是個操作符不是個函數。
    char c;
    sizeof c;  //變量名可以不加括弧
8. 當適用於一個結構類型或變量, sizeof 返回實際的大小,
    當適用一靜態地空間數組, sizeof 歸還全部數組的尺寸。
    sizeof 操作符不能返回動態地被分派了的數組或外部的數組的尺寸

 

sizeof、strlen計算字符數組、字符指針空間

image

總結一下:

1). sizeof的結果是類型的大小,區分類型之后,sizeof的結果也就命了,sizeof的結果是在編譯期決定的,計算的占據的內存大小。

     srelen的結果是在運行期間決定,計算的是實際長度,strlen只能以char*作參數,以\0作為結束符, 以上的例子中,紅色部分的strlen計算是錯誤的,

     因為在str的數據存儲中並沒有 一個\0字符,所以strlen的結果看似有點異常。

2). 注意在計算sizeof的時候:

     char str[] = "abc";  類型為char[4],   sizeof(str) = 4*sizeof(char) = 4.

3). sizeof(express),其中的express在編譯過程中是不會被編譯的,而是被替代類型。

     例如: int a = 1; sizeof(a=2);

     此時的express為a=2,在編譯過程中被替換為sizeof(int),所以在執行完之后,a仍然是等於1.

4). 對函數使用sizeof,在編譯階段會被替換為函數的返回值的類型取代

     例如: int f(){return 0;}  sizeof(f());的結果為4.

             void f(){}            sizeof(f());編譯過程中會出現錯誤,替換之后的sizoeof(void)編譯無法通過.

另外關於sizeof,還可以參加本人的其他文章:http://www.cnblogs.com/rollenholt/archive/2012/03/19/2405455.html#top


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM