天天看點

數組(array)應用Array of Strings in C++Array Decay in C++How to find size of array in C/C++ without using sizeof ?

Array of Strings in C++

在C++中有3中方法可以建立Array of Strings

  1. 使用二維數組(C/C++)

1.1 用字元數組表示的字元串

字元數組的初始化有兩種

char str2[6]="china";
    char str3[5] = {'c','h','i','n','a'};
           

第一種初始化方式必須要為'\0'配置設定空間,也就是說, 用一個字元串初始化字元數組時,字元數組除了要儲存這個字元串以外,還必須要儲存至少一個'\0',

第二個初始化方式是用每一個單獨的字元去初始化字元數組,在這種情況下不需要儲存'\0', 隻要滿足字元數組的空間>=所要配置設定的字元大小即可。

注意:字元數組的指派不能用一個字元串指派,而隻能使用單個字元去對數組元素一一指派。

在C語言中還可以用字元指針指向字元串:

char *str1="china";
           

str指向的是大小為5位元組的記憶體空間,在這個空間中沒有'\0',這個空間的首位址儲存在str1中。

不同于字元數組,對字元指針可以使用字元串整體指派:

str1 = ”I love China";
           
char color[][10] = {"blue","Red","orange","yellow"};
           
1.2 用二維數組表示多個字元串
char color[][10] = {"blue","Red","orange","yellow"};//sizeof(color) = 40
            
for(int i = 0; i < 4;i++)
    cout<<color[i]<<endl;
           
//由于C/C++的多元數組是行優先,是以color數組的元素分布如下:
           
b l u e \0 \0 \0 \0 \0 \0
R e d \0 \0 \0 \0 \0 \0 \0
o r a n g e \0 \0 \0 \0
y e l l o w \0 \0 \0 \0

color[i]就是第i行的字元串的首位址。

輸出是

數組(array)應用Array of Strings in C++Array Decay in C++How to find size of array in C/C++ without using sizeof ?
這種方法的缺點:
  • Number of Strings and Size of String – both the values are fixed.
  • A 2D array is allocated, whose second dimension is equal to maximum sized string which causes wastage of space.
  1. 使用string(C++)
#include<bits/stdc++.h>
using namespace std;
 
int main()
{
    // Initialize String Array
    string colour[4] = {"Blue", "Red", "Orange", "Yellow"};
     
    // Print Strings
    for (int i = 0; i < 4; i++) 
        cout << colour[i] << "\n";
}
           

這種方法的缺點:

Array is of fixed Size

  1. 使用vectors(C++) STL Container Vector can be used to dynamically allocate Array.
    // C++ program to demonstrate vector of strings using
    #include<bits/stdc++.h>
    using namespace std;
     
    int main()
    {
        // Declaring Vector of String type
        vector <string> colour;
     
        // Initialize vector with strings using push_back 
        // command
        colour.push_back("Blue");
        colour.push_back("Red");
        colour.push_back("Orange");
        colour.push_back("Yellow");
     
        // Print Strings stored in Vector
        for (int i=0; i<colour.size(); i++)    
            cout << colour[i] << "\n";    
    }
               
    從以上3點來看,vector應該是c++中建立字元串數組最好的方法了

注意:‘\0'在C語言中是 字元串結束符,是以隻有數組在處理字元串時才會用多餘的一個位元組來儲存它,在其他情況(非字元數組)下,數組不會儲存它

Array Decay in C++

What is Array Decay?

數組退化是指數組丢失了數組元素的類型和數組的大小。這通常發生在向函數按值傳遞或傳遞指針參數時,結果就是僅僅把實參的首位址傳給了形參的數組,這時數組就退化為一個指針,數組的大小也會變成指針的大小而不是原數組的大小。

舉個簡單的例子:

#include <iostream>
using namespace std;
 
void findSize(int arr[])
{
    cout << sizeof(arr) << endl;
}
 
int main()
{
    int a[10];
    cout << sizeof(a) << " ";
    findSize(a);
    return 0;
}
           
輸出
40 8      
d
// C++ code to demonstrate array decay
#include<iostream>
using namespace std;
 
// Driver function to show Array decay
// Passing array by value
void aDecay(int *p)
{
    // Printing size of pointer
    cout << "Modified size of array is by "
            " passing by value: ";
    cout << sizeof(p) << endl;
}
 
// Function to show that array decay happens 
// even if we use pointer
void pDecay(int (*p)[7])
{
    // Printing size of array
    cout << "Modified size of array by "
            "passing by pointer: ";
    cout << sizeof(p) << endl;
}
 
int main()
{
    int a[7] = {1, 2, 3, 4, 5, 6, 7,};
 
    // Printing original size of array
    cout << "Actual size of array is: ";
    cout << sizeof(a) <<endl;
 
    // Calling function by value
    aDecay(a);
     
    // Calling function by pointer
    pDecay(&a);   
 
    return 0;
}
           
輸出
Actual size of array is: 28
Modified size of array by passing by value: 8
Modified size of array by passing by pointer: 8      

How to prevent Array Decay?

一個典型的解決辦法就是把數組大小也作為一個參數傳給函數,并且對數組參數不要用sizeof。

另外一個解決辦法就是把數組按引用傳遞給函數,這樣就避免了數組轉化為指針,也就避免了退化。比如

// C++ code to demonstrate prevention of
// decay of array
#include<iostream>
using namespace std;
 
// A function that prevents Array decay
// by passing array by reference
void fun(int (&p)[7])
{
    // Printing size of array
    cout << "Modified size of array by "
            "passing by reference: ";
    cout << sizeof(p) << endl;
}
 
int main()
{
    int a[7] = {1, 2, 3, 4, 5, 6, 7,};
 
    // Printing original size of array
    cout << "Actual size of array is: ";
    cout << sizeof(a) <<endl;
 
    // Calling function by reference
    fun(a);
 
    return 0;
}
           
其它知識點:
  • 數組指針:int (*t)[N] 表示一個數組指針,它的意思是,t是一個指向 在記憶體中連續存儲的 N個int資料所組成的 塊的指針,N必須與實參二維數組的列值相同。先看小括号得知t是一個指針,往右看得知它指向的是數組,再看最左邊,數組元素是int型的。(所有的指針都可以這麼解讀,包括函數指針)
  • 指針數組 :int (*t)[N] 表示t是一個數組,其中的元素是int*類型。
  • 數組引用:int (&t)[N] 表示t是一個數組的引用,其它的意義同數組指針,可以作為其它數組的呃别名。

How to find size of array in C/C++ without using sizeof ?

舉例:

// C++ program to find size of an array by using a 
// pointer hack.
#include <bits/stdc++.h>
using namespace std;
 
int main()
{
    int  arr[] = {1, 2, 3, 4, 5, 6};
    int size = *(&arr + 1) - arr;
    cout << "Number of elements in arr[] is "
         << size;
    return 0;
}
           

在解釋原理之前,先說明 arr與&arr的差別

如果分别列印arr和&arr的值,你會發現這兩者的值是一樣的:

printf("array=%p : &array=%p\n", array, &array);  
   printf("array+1 = %p : &array + 1 = %p", array+1, &array+1);
           

然而将它們分别加1以後的值就不一樣了,這是因為 arr與&arr雖然都指向相同的位址,但是位址的類型是不同的。

  • arr指向的是數組内的第一個元素的首位址,該元素類型是int,是以arr+1相當于第一個元素的首位址加4
  • &arr指向的是整個數組的首位址,類型是數組,是以&arr+1就相當于數組的首位址加數組的大小(機關是byte,本例是24=0x18)

原理:

&arr ==> Pointer to an array of 6 elements.
         [See this for difference between &arr
          and arr]   

(&arr + 1) ==> Address of 6 integers ahead as
               pointer type is pointer to array
               of 6 integers.

*(&arr + 1) ==> Same address as (&arr + 1), but 
                type of pointer is "int *".類型轉化

*(&arr + 1) - arr ==> Since *(&arr + 1) points 
                   to the address 6 integers
                   ahead of arr, the difference
                   between two is 6. 利用指針減法