1、二維(多維)數組
多維數組定義
float y[4][3]; //4行3列
二維數組可以看作是一個元素爲另一個一維數組的一維數組;
三維數組可以看作元素爲二維數組的一維數組…
因此,在C語言中,下標變量應寫作:y[i][j],而不能寫成:y[i, j]
多維數組的初始化
int y[4][3] = {
{ 1, 3, 5 },
{ 2, 4, 6 },
{ 3, 5, 7 },
};
存儲情況如下:
int y[4][3] = { 1, 3, 5, 2, 4, 6, 3, 5, 7 }; 也同上,因爲在C語言中,數組元素按行存貯。
多維數組使用
如果把一個二維數組作爲參數,則在函數定義中,形參數組的說明中必須指明列的數目,而行的數目可空着不寫。
如:
main( )
{
float a[4][3], b[3][4], c[4][4];
fun(a, 4, b , 3 , c, 4);
}
void fun(float x[ ][3],int rowx, float y[ ][4],int rowy, float z[ ][4], int rowz)
{
}
2、指針
指針是一種數據類型;
指針變量:存放的是所指對象的地址
在C語言中,允許指針指向任何類型的對象(可指向基本類型、構造類型),甚至可指向其它指針或指向函數。
指針賦值
通過&(取地址運算符)使指針指向某個對象
int i = 100;
int *pi;
pi = &i;
通過指向同一數據類型的指針賦值
double i, *pi, *pj;
i = 10.24;
pi = &i;
pj = pi;
唯一可以賦給指針的整數值:0,表示空指針,一般寫成常量NULL
指針可以在程序運行的不同時刻指向不同的對象
通過 * 一元運算符(解尋址或解引用運算符)取得指針所指向的數據值
int i = 10, y = 20, *pi;
pi = &i;
y = *pi;
當pi指向具體對象y時,*pi爲pi所指對象的值,以後凡是對y的引用,都可用*pi來代替
3、可以通過將指針作爲函數參數來改變多個變量的數據,如下:
void swap ( int *px, int *py) //形參定義爲指針
{
int temp;
temp = *px;
*px = *py;
*py = temp;
}
main( )
{
int a =2, b = 3;
swap ( &a, &b); //實參傳遞的是變量的地址
}
關於指針的一些說明:(無小括號時,右結合)
4、動態內存管理(malloc與free)*
在C中可以使用標準庫函數malloc動態爲指針變量申請一塊內存空間(初始化指針變量)
void * malloc ( unsigned int size );
使用malloc初始化指針變量的常見用法:
char *s; int *intptr;
s = (char *)malloc(32); /* s指向大小爲32個字節(字符)的空間*/
s = (char *)malloc(strlen(p)+1); /* s指向能正好存放字符串p的空間*/
intptr = (int *)malloc(sizeof(int)*10);/* ptr指向能存放10個整型元素的空間*/
使用malloc申請到的動態空間在不用時應使用函數free釋放。如,free(s);
使用malloc和free函數要用:#include <stdlib.h>
運算符sizeof用來計算所在系統中某種類型或類型變量所佔的長度(以字節爲單位)。如:
sizeof(int),sizeof(n),sizeof(double)
具體值取決於系統,通常int或int變量長度爲4,double爲8
5、指針應具有非零(無符號整數)值,如將0(通常**#define NULL 0**)賦給予指針,則該指針沒有指向任何具體對象,即空指針。
6、在C語言中,數組的名字就是指向該數組第一個元素(下標爲0)的指針,即該數組第一個元素的地址,也即數組的首地址
7、當指針指向某一數組時:
a、指針和整數可以進行加減。(使用指針訪問數組)
若p爲指針,則p+n和p-n是合法的,同樣p++也是合法的,它們的結果同指針所指對象類型相關。
pi = a;
pi++; //這時pi指向a[1],*pi爲a[1]
pi+=6; //這時pi指向a[7],*pi爲a[7]
b、兩個指向同一類型的指針,可進行= = , > , <等關係運算,其實就是地址的比較。
if ( pi==pj ) 用來判斷pi是否超出了數組表示的範圍
c、兩個指向同一數組成員的指針可進行相減
如, pj-pi表示數組的長度
d、當P1,和P2指向同一類型時,可以進行賦值
如:py = px,則px,py指向同一對象。
8、兩指針不能相加!!!!!
如圖,計算中間指針,不能寫成 mid = (low + high ) /2,應寫成 mid = low + (high – low)/2
9、幾對指針的區別:
a、 p++和p+1的區別
p++結果爲p指向下一元素;p+1結果爲下一元素的指針,但p本身不變。
b、y = *px + 1和y= *(px + 1)的區別
*px+1爲取px所指對象內容加1 ;*(px+1)爲px指針加1,並取結果指針所指對象內容;
c、y = (*px)++和y = *px ++的區別
(*px)++爲先取px所指對象內容進行運算,然後對其加1;*px++爲先取px所指對象內容進行運算,然後指針px加1。(*p++等價於*(p++),*和++同優先級,右結合)
如下圖:
10、常用標準字符串庫函數
#include <string.h>
int strlen(char s[ ]);
char *strcpy(char s[ ], char t[ ]);
char *strcat(char s[ ], char t[ ]); //字符串連接
int strcmp(char s[ ], char t[ ]);
//s爲結果
11、數組名和指針
int a[10], x;
int *pa;
pa =a;
一般有:a[i] , *(pa+i) , *(a+i) 代表同一數據
但特別注意:數組名和指針(變量)是有區別的,前者是常量,而後者是變量
因此,儘管我們可寫pa =a;
但決不能寫:a = pa ; a++; 等。
12、爲什麼使用指針?
- 擴展了語言的功能,如通過傳遞指針來修改實參變量、或通過返回指針來返回數組等;
- 能夠更方便的組織和操作數據,如,離散數據的組織和訪問(鏈表,樹等);
13、指針與字符串常量
對於字符串常量,可以把它看成一個無名字符數組,C編譯程序會自動爲它分配一個空間來存放這個常量,字符串常量的值是指向這個無名數組的第一個字符的指針,其類型是字符指針。
所以,printf(“a constant character string\n”); 傳遞給函數的是一個無名數組第一個字符的指針。
注意:字符數組和字符指針使用時容易混淆,如下:
14、指針數組
指針數組就是由指針組成的數組,即該數組的每一個元素都是指向某一對象的指針;
指針數組與二維數組的區別:
a、儘管二維字符數組與字符指針數組在存儲形式上不同,但它們在初始化形式以及訪問元素方式上卻是相同的。
例如,無論是指針數組,還是二維數組,下面兩種形式訪問的都是同一個元素,結果都是字符串”Friday”中的字符’y’。
*(days[5]+5) , days[5][5]
b、使用指針數組來存放不同長度的字符串可以節省存貯空間。
15、一些分析!!!!
#include <stdio.h>
char a[4][5] = { "abcd", "efgh", "ijkl", "mnop" };
main( )
{
printf("a=%x, a[0]=%x, &a[0][0]=%x\n", a, a[0], &a[0][0]);
printf("a+1=%x, a[0]+1=%x, &a[0][1]=%x\n", a+1, a[0]+1, &a[0][1]);
printf("**(a+1)=%c, *(a[0]+1)=%c\n", **(a+1), *(a[0]+1));
}
二維數組a如下圖:
運行結果如下:
16、類型定義(typedef)
類型定義的語法格式爲:
typedef 原類型名 新類型名;(別忘了分號)
如:
typedef int LENGTH;
typedef char * STRING;
變量說明爲:
LENGTH len, maxlen;
STRING ps,lineptr[LINES];
這與如下直接說明等價:
int len, maxlen;
char * ps, * lineptr[LINES];
定義數組類型:
typedef int VECT [100];
typedef double MAT [5][5];
VECT v1,v2;
MAT m1,m2;
相當於:
int v1[100], v2[100];
double m1[5][5], m2[5][5];
必須強調,typedef說明均不產生新的數據類型,也不定義存儲單元,它只是給已有的類型又增添了新的類型名,沒有產生新的語義,即用這種方法所說明的變量與明確指出說明的那些變量有相同的性質。
類型定義的必要性:
- 將程序參數化,便於移植;
- 爲程序提供較好的說明信息,便於理解;
類型定義的一個常見用法是用來定義結構類型,如下:
typedef struct {
int day;
int month;
int year;
char week_name[4];
} DATE;
DATE d, *pd, ad[10];
//使用typedef定義結構類型名後,結構變量的定義(或說明)就更簡潔了。
17、結構體成員的引用
a、結構名 . 成員名
b、結構指針 -> 成員名
pd->year與(*pd).year 是完全等價的,這是由於在C語言中指向結構的指針使用非常頻繁,特爲此設立了一個新運算符(->)。
18、當數組中的每一個元素都是同一結構類型的變量時,則稱該數組爲結構數組。
例如: struct person table[100];
19、結構與聯合(union,共用體)的異同
- 在定義或說明形式上,union和struct很類似,但在任何時刻聯合只允許聯合中說明的某一成員留在聯合裏。
- 結構由多個成員(分量)所組成,而聯合只有一個成員,只不過該成員的名字和類型可以在規定的幾個裏選定一個。
- 因此,聯合可以看作是一個特殊的結構,其所有成員在結構中的位移量都是0,當對聯合變量分配存貯空間時,應保證它能容納最大的一個成員的大小,而存貯空間的邊界應能適於聯合中的所有可選成員的類型。
- 對聯合的初始化只能對應於它的第一個可選成員。
- 對聯合成員的引用方式完全和結構的情況一樣。