1、数组初始化 :
数组:元素数目+元素类型;
int powers[4] = {1, 2, 4, 6} ; // 花括号,逗号隔开;未经初始化的数组,编译器会使用存储单元中的已有的数值给它赋值;
days[] = {31,28,31,30,31,30,31,31,30,31,30,31}; // 允许,编译器会根据列表中数值数目来确定数组大小;
指定初始化项目: int arr[6] = {212};// 其他未初始化的元素都被设置为0;多次对同一元素赋值,最后一次有效;
指针初始化 :
int* p = NULL;
int* p = new int[10]; // 注意
delete
[]p(数组) 或者delete p(非数组);
指针和数组粘合:
// 一维数组
char str[10] = { '1', '2', '3'};
char* p = str;
// 一维数组
char str[10] = { '1', '2', '3'};
char* p = str;
// 普通变量
int a = 1;
int* pa = &a;
若函数参数为指针,且指向二维数组,调用该函数时,需要带[0];例:
rain_ptr
(
rain
[0]);
2、const 声明数组:
使用const 使数组只读,程序可以从数组中读取数值,但是不能像数组中写数据;
const int days[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; // 声明之后不能再对它赋值;
形参使用const:
int sum(const int ar[], int n);// 定义ar所指向的数组值为常量,不允许修改;
指向常量的指针不能修改数值,将常量或非常量数据的地址赋值给指向常量的指针时合法的;但只有非常量的数据地址才可以赋值给普通指针;
const double* p = days[] ; 指针指向的值不能被改变,但可以改变地址来改变指向的数组值;
double* const p = days[] ; 指针地址不能变;
守则:在能加const的地方都加上
3、遍历index,打印数组中各个元素:
int days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
for (int index = 0; index < 12; index++)
printf("Month %d has %2d days.\n", index +1, days[index]);
仅字符数组可以直接整体打印,但字符数组
必须有 0 结尾;标识符用 %s;
char
ar[] = {
'a'
,
's'
,
'c'
,
'\0'
};
printf(
"%s\n"
,ar);
4、为数组赋值:
c语言不支持把数组作为一个整体赋值,也不支持花括号括起来的列表形式赋值(初始化的时候除外);
通过循环数组索引对数组成员赋值:
int counter, evens[12];
for (counter = 0; counter < 12; counter++)
evens[counter] = 2 * counter;
5、多维数组:
float rain[5][12]; // 5个由12个浮点数组成的数组的数组;
初始化二维数组:
const float rain[YEARS][MONTHS] =
{
{4.3,4.3,4.3,3.0,2.0,1.2,0.2,0.2,0.4,2.4,3.5,6.6}, // 逗号分离隔的5个数值列表;
{8.5,8.2,1.2,1.6,2.4,0.0,5.2,0.9,0.3,0.9,1.4,7.3}, // 某一行赋值错误,不会影响下一行;
{9.1,8.5,6.7,4.3,2.1,0.8,0.2,0.2,1.1,2.3,6.1,8.4},
{7.2,9.9,8.4,3.3,1.2,0.8,0.4,0.0,0.6,1.7,4.3,6.2},
{7.6,5.6,3.8,2.8,3.8,0.2,0.0,0.0,0.0,1.3,2.6,5.2}
};
6、指针和数组:
数组名也是该数组首元素的地址,指针说明符%p,通常以十六进制显示值;系统按字节编址,对指针+1 ,是对该指针增加一个
存储单元,对数组,会增加到下一个元素的地址;
dates +2 == &dates[2];// 地址相同
*(dates + 2) == dates[2];// 相同的值 // 间接运算符* 的优先级高于+;
ar为指针或数组,均有 ar[i] 和 *(ar+i) 等价;
ar为指针时,才能使用 ar++;
计算数组长度:
int ar [] = {11, 5, 9, 6};
int n = sizeof ar / sizeof (int );
指针指向的数组长度怎么计算??无法计算。
7、函数、数组、指针:
仅 在函数原型或函数定义头时,可以用 int *ar 代替 int ar[]; 此时指针与数组等效;
声明数组参量:
如果实际参数是一个数组名,形式参量必须是与之匹配的指针;
函数原型中,以下4种可相互等效:
int sum (int *char, int n)
int sum (int *, int )
int sum (int ar[], int n)
int sum (int [], int )
函数定义时,名称不能省略,以下2种可相互等效 :
int sum (int *char, int n)
{
}
int sum (int ar[], int n)
{
}
说明符打印sizeof()的返回值,用%zd;
8、使用指针参数:
// 用index遍历元素,求数组元素和;
int main(void)
{
int marbles[SIZE] = {20,10,5,39,4,16,19,26,31,20};
long answer;
answer = sum(marbles, SIZE);
return 0;
}
int sum(int ar[], int n)
{
int i;
int total = 0;
for( i = 0; i < n; i++)
total += ar[i];
return total;
}
// 定义两个指针,start 和 end 指明指针起始和结束地址;
int main(void)
{
int marbles[SIZE] = {20,10,5,39,4,16,19,26,31,20};
long answer;
answer = sump(marbles, marbles + SIZE);
return 0;
}
int sump(int * start, int * end)
{
int total = 0;
while (start < end) // 结束地址指向数组结尾之后的下一个元素
{
total += *start;
// 等价total += *start++; * 和 ++优先级相等,但结合方式是从右到左;
start++;
}
return total;
}
课后习题
第一题:二维数组转化为一维数组:
for
(
year
= 0,
total
= 0;
year
<
YEARS
;
year
++)
{
for
(
month
= 0,
subtot
= 0;
month
<
MONTHS
;
month
++)
subtot
+=
rain
[
year
*
MONTHS
+
month
];// 二维转为一维,求所有元素之和;
printf
(
"%d %.1f\n"
,
year
,
subtot
);
}
第二题:用数组和指针复制一个数组;
// 用数组符号进行拷贝
voidcopy_arr(doublesource[],doubletarget1[],intn)
{
for ( inti = 0; i < n;i++)
{
target1[i] = source [i ];
printf("%.2f ", target1 [i ]);
}
printf("\n");
}
// 用指针进行拷贝
void copy_ptr (double* source , double *target2 , int n )
{
for ( inti = 0; i < n;i++)
{
*( target2 + i) = *(source+ i);
printf("%.2f ", target2 [i ]);
}
printf("\n");
}
第十题:初始化数组、翻倍数组中各元素;
double
*
ar
=
get_double
(
n
,
m
);
double
*
init_ar
(
int
n
,
int
m
)
{
double
*
ar
=
new
double
[
n
*
m
]; // 用new创建指针数组;
// 初始化声明的数组
for
(
int
i = 0; i < n; i++)
{
for
(
int
j = 0; j < m; j++)
{
ar[i * m +
j
] = i + j / 10.;
printf(
"%.1f "
, ar[i * m +
j
]);
// 注意是乘以内存循环参数
}
printf(
"\n"
);
}
printf
(
"\n"
);
return
ar;
}