關於數組的一些運算
我們先看看運算符sizeof和函數strlen函數的作用定義和用法。
sizeof:sizeof是C/C++中的一個操作符(operator),簡單的說其作用就是返回對象或者類型所佔內存的字節數。
MSDN上的解釋爲:
The sizeof keyword gives the amount of storage, in bytes, associated with a variable or a type(including aggregate types). This keyword returns a value of type size_t.
其返回值類型爲size_t,在頭文件stddef.h中定義。這是一個依賴於編譯系統的值,一般定義爲
typedef unsigned int size_t;
sizeof有三種語法形式,如下:
sizeof(object);//sizeof(對象);
sizeof(type_name);//sizeof(類型);
sizeofobject;//sizeof對象;
sizeof 的應用數組的sizeof值等於數組所佔用的內存字節數,如:
char a1[] = "abc";
int a2[3];
sizeof( a1 ); // 結果爲4,字符 末尾還存在一個NULL終止符
sizeof( a2 ); // 結果爲3*4=12(依賴於int)
值得一提的是,sizeof(只有數組名),則表示的是數組佔用的大小。sizeof(arr+0)則表示第一個元素
佔用的大小。不要誤以爲sizeof是直接計算數組長度的,當計算長度時應該使用:
int c1 = sizeof( a1 ) / sizeof( char ); // 總長度/單個元素的長度
int c2 = sizeof( a1 ) / sizeof( a1[0] ); // 總長度/第一個元素的長度
———————————————————————————————————————————————————
strlen:strlen所作的僅僅是一個計數器的工作,它從內存的某個位置(可以是字符串開頭,中間某個位置,甚至是某個不確定的內存區域)開始掃描,直到碰到第一個字符串結束符'\0'爲止,然後返回計數器值(長度不包含'\0')。其頭文件是string.h
———————————————————————————————————————————————————
1.先看看一維數組的運算。
int arr[]={1,2,3,4};
printf("%d\n",sizeof(arr)); //16
printf("%d\n",sizeof(arr+0)); //4
printf("%d\n",sizeof(*arr)); //4
printf("%d\n",sizeof(arr+1)); //4
printf("%d\n",sizeof(arr[1])); //4
printf("%d\n",sizeof(&arr)); //4
printf("%d\n",sizeof(&arr+1)); //4
printf("%d\n",sizeof(&arr[0])); //4
printf("%d\n",sizeof(&arr[0]+1));//4
對上面一維數組進行了簡單的運算和預測。
來看看輸出的結果如何:
真實結果和預測結果一毛一樣。
還有一個sizeof的坑:
void foo3(char a3[3])
{
int c3 = sizeof( a3 ); // c3 ==
}
void foo4(char a4[])
{
int c4 = sizeof( a4 ); // c4 ==
}
這裏的c3 答案並不是3,因爲此時a3並不是作爲數組傳進函數,而是指針,
相當於char *a3,我們只是將a3地址傳入,所以指針所佔爲4字節。
——————————————————————————————————————————————————
字符數組:
例:
int main()
{
char arr[]={'a','b','c','d','e','f'};
printf("%d \n",sizeof(arr)); //6 整個數組元素大小。
printf("%d \n",sizeof(arr+0)); //4 首元素地址
printf("%d \n",sizeof(*arr)); //1 第一個元素大小
printf("%d \n",sizeof(arr[1])); //1 第一個元素大小
printf("%d \n",sizeof(&arr)); //4 數組地址
printf("%d \n",sizeof(&arr+1)); //4 數組下一位地址
printf("%d \n",sizeof(&arr[0]+1));//4 第二個元素地址
printf("%d \n",strlen(arr)); //隨機值直到遇到 \0
printf("%d \n",strlen(arr+0)); //隨機值直到遇到 \0
//printf("%d \n",strlen(*arr)); //相當於strlen(97),error。
//printf("%d \n",strlen(arr[1])); //相當於strlen(97),error。
printf("%d \n",strlen(&arr)); //隨機值 從數組地址往後直到\0
printf("%d \n",strlen(&arr+1)); //隨機值 從數組下一位地址直到\0
printf("%d \n",strlen(&arr[0]+1)); //隨機值 從第二個元素數到\0
return 0;
}
結果展示:
帶有指針的字符數組:
例:
int main() { char *p = "abcdef"; printf("%d\n",sizeof(p)); //4 指針的大小 printf("%d\n",sizeof(p+1)); //4 首元素地址+1,b的地址,大小爲4 printf("%d\n",sizeof(*p)); //1 解引用 一個字符所佔的大小 printf("%d\n",sizeof(p[0]));//1 相當於*(p+0),對第一個元素解引用 printf("%d\n",sizeof(&p)); //4 指針的地址 printf("%d\n",sizeof(&p+1));//4 指針下一位的地址 printf("%d\n",sizeof(&p[0]+1));//4 b的地址 printf("%d\n",strlen(p)); //6 字符個數 printf("%d\n",strlen(p+1)); //5 從第二個元素開始直到\0 //printf("%d\n",strlen(*p));//相當於strlen(97),error //printf("%d\n",strlen(p[0]));//相當於strlen(97),error printf("%d\n",strlen(&p)); //隨機值,指針的地址往後遇到\0 printf("%d\n",strlen(&p+1));//隨機值,p的地址下一位往後遇到\0 printf("%d\n",strlen(&p[0]+1));//5 從第二個元素開始數到\0 return 0;結果:
———————————————————————————————————————————————————
二維數組:
進行二維數組運算時先搞清楚二維數組的儲存方式。
將二維數組看成一維數組的方式存儲,具有連續性。
例:
int main()
{
int a[3][4]={0};
printf("%d\n",sizeof(a)); //48 12個元素,每個4字節
printf("%d\n",sizeof(a[0][0])); //4
printf("%d\n",sizeof(a[0])); //16 第一行的元素所佔字節
printf("%d\n",sizeof(a[0]+1)); //4 其中a[0]表示第一行的首元素,+1就是第一行的第二個元素大小
printf("%d\n",sizeof(a+1)); //4 其中a表示總數組中的首元素,由圖得是a[0]一行,+1表示第二行第一個元素
printf("%d\n",sizeof(&a[0]+1)); //4 第一行地址+1,爲第二行的地址
printf("%d\n",sizeof(*a)); //16 總數組的首元素所佔大小,就是第一行所佔的大小
printf("%d\n",sizeof(a[3])); //16 雖然沒有第四行,但是默認和前面行數大小相等
return 0;
}
結果:
———————————————————————————————————————————————————
總結:運算大小繞來繞去有點凌亂,但是反覆琢磨也能發現其中規律。
當數組名錶示整個數組時,只有這兩種情況:
1.arr(數組名),當括號裏面只有數組名時。
2.&數組名,取數組名地址時。
除了這兩種情況,其他數組名出現時,大部分都表示數組的首元素地址。