一.数组。
含义:存储一些同类型数据的地方,数组是一块连续的内存地址。
数组名代表这块地址的起始地址。
即:
#include <stdio.h>
int main()
{
int s[3]={1,2,3};
printf("s 的地址是:%p\n", s);
printf("s[0] 的地址是:%p\n", &s[0]); //s与s[0]地址一样。
return 0;
}
定义方式:类型 数组名[元素] 例:int a[3]; char b[2]; double c[3];
#注意:不能动态定义数组,及元素个数必须是已知数。数组的长度在编译时才被确认也是可行的。
数组每个元素的尺度等于它们所占的宽度。
数组初始化:
a.所有元素初始化为0.
int a[10]={0};//只是将第一个元素初始化为0,后面的默认初始化为0
b.所有元素赋予不同的值。
int a[5]={1,2,3,4,5};
c.只给一部分赋值。
int a[10]={1,2,3,4,4,5,};//后面的自动初始化为0
int a[10]={[2]=3,[4]=3,[9]=2};//为被初始化的自动初始化为0
#注意:未初始化的一块地址空间,其值是空间本身的值。
小技巧:给出数值的值可以省略其数组长度。
int a[]={1,2,3,4,5,6};//相等于int a[6]
访问数组:下标访问,从0开始。
数组名[下标]
例:
int a[0];//访问a数组的第一个元素。
#注意:别越界访问。
数组小例子:
#include <stdio.h>
#define NUM 10
int main()
{
int s[NUM];
int i,sum=0;
for(i=0;i<10;i++)
{
printf("请输入第%i位同学的成绩:",i+1);
scanf("%d",&s[i]);
sum += s[i];
}
printf("成绩录入完毕,该次考试的平均分是:%.2f\n",(double)sum \ NUM);
}
字符数组
字符数组以'\0'为结束标准。
例:
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
处理字符串的函数:
函数 | 目的 |
strcpy(s1,s2); |
复制字符串s2到字符串s1。
|
strcat(s1,s2); | 连接字符串s2到字符串s1的末尾。 |
strlen(s1); | 返回字符串s1的长度。 |
strcmp(s1,s2); | 如果s1和s2的ASCII是相同的,则返回0;如果s1<s2则返回小于0;如果s1>s2则返回大于0。 |
strchr(s1,ch); | 返回一个指针,指向字符串s1中字符ch的第一次出现的位置。 |
strstr(s1,s2); | 返回一个指针,指向字符串s1中字符串s2的第一次出现的位置。 |
#注意:strcpy一定要s1能够容纳s2,不如会溢出。建议拷贝采用strncpy(s1,s2,s)其中s是限制拷贝个数,strncpy没有把最后的'\0'字符串结尾标志自动添加,需要自己添加进去。strncat(s1,s2,s)也是和拷贝差不多,但strncat与strcat相比,它会自动追加一个结束符。strncmp(s1,s2,s)对比前面s个字符。
多维数组
点、线、面。点一个内存单元、线一维数组、面二维数组。三维立体空间。
二维数组的定义:类型 数组名[常量表达式][常量表达式]
例:
int a[23][3];//23*3、23行3列
char b[3][4];//4*3、3行4列
double c[5][7];//5*7、5行7列
如图:

但内存是线性的一块连续的地址空间表达的。如图:
二维数组的初始化:
a.由于二维数组是线性存放因此可以将所有数据写在一个花括号内:int a[2][3]={1,2,3,4,5,6};
也可以:int a[2][3]={{1,2,3},{4,5,6}};
小技巧:也可以省略一维的常量,注只能省略第一维的常量:int a[][3]={{1,2,3},{4,5,6}};
b.也可以仅对部分元素赋初始值,未赋值的0填充:int a[2][3]={{0,1},{2}};
c.指定初始化元素:int a[2][3]={[2][1]=5,[2][2]=3};
二维数组的访问:数组名[下标][下标]
例:
a[0][0];//访问a中第一个数组,一行一列
a[0][2];//访问a中第三个数组,一行三列
a[3][4];//访问a中第三行四列
#注意:防止越界访问。
二.指针。
含义:指针是一个变量,其值是另一个变量的地址。指针占4个字节,因为地址是以4个字节存放的(注:有的系统肯不一致)。
定义指针:类型名 *指针名;
例:
int *ip; /* 一个整型的指针 */
double *dp; /* 一个 double 型的指针 */
float *fp; /* 一个浮点型的指针 */
char *ch; /* 一个字符型的指针 */
取值运算符与取址运算符:
&代表了取其地址。
*代表了取其值。
char *pa = &a; //取其a变量的地址给pa指针
printf("%c\n", *pa); //取其pa指向的地址中的变量的值。
而指针名可以看作是这个指针的地址,这样*就解引用,P=&num就能赋值其地址。
注意:指针在定义以后一定要初始化,未初始化的指针也称野指针。
void指针与NULL指针
void指针被称之为通用指针。可以指向任何类型的数据,任何类型的指针都可以赋值给void指针。
void指针转换成其他类型的指针,加个强制类型转换。
例:
#include <stdio.h>
int main()
{
int num = 1024;
int *pi = #
char *ps = "char";
void *pv;
pv = pi;
printf("pi:%p, pv:%p\n", pi, pv);
printf("*pv:%d\n",*(int *)pv);
//如果不加强制转换无法打印,printf不知道pv大小。printf("*pv:%d\n",*pv);
pv = ps;
printf("ps:%p, pv:%p\n", ps, pv);
prinntf("pv:%s\n", (char *)pv);
//不加强制类型转换可以,字符串专属“\0”,加上规范。字符串不用*解引用。
return 0;
}
NULL指针用于赋值给那些没有确切的地址的指针。赋值为NULL的指针被称之为空指针。
原型:#define NULL ((void *)0)
注意:NULL不是NUL,NUL表示字符串的结尾"\0"。NUL可在ASCII表看到。
三.函数
定义:对若干代码的封装。
分类:自定义函数、库函数。
库函数:直接调用,系统、第三方编写好。如printf();
自定义函数三步骤:声明、定义、调用。
注意:当函数在main函数之前定义的可以不用声明,建议最好声明。函数声明必须放在函数定义之前。
函数声明:返回类型 函数名(参数); (返回类型:无返回类型用void、不写默认返回int。声明时可以不写参数的名字但必须要写其参数类型)
函数定义:返回类型 函数名(参数){函数主体} (无参数也必须打()、函数内变量名与mian内变量名可以一样,其是作用域。)
函数调用:函数名(传入参数);
- #include <stdio.h>
- /* 函数声明 */
- int max(int num1, int num2);
- int main ()
- {
- /* 局部变量定义 */
- int a = 100;
- int b = 200;
- int ret;
- /* 调用函数来获取最大值 */
- ret = max(a, b); //传入的参数被称为实参,实际参数。
- printf( "Max value is : %d\n", ret );
- return 0;
- }
- /* 函数返回两个数中较大的那个数 */
- int max(int num1, int num2) //如果将函数的定义放在main函数之前可以省略函数的声明。这里的参数被称之为形参,形式参数
- {
- /* 局部变量声明 */
- int result;
- if (num1 > num2)
- result = num1;
- else
- result = num2;
- return result; //当函数执行到return时函数结束返回其必有的返回值。
- }
参数
a.形参与实参
形参:函数定义时所用的参数。
实参:函数调用时传入的参数。
b.传值与传址
传值与传址的区别在于可以改变其原有数据的值。传址用指针、数组,传值用变量。
c.可变参数(函数参数的传入是可变的)
预备知识:需要使用头文件stdarg.h、内的va_list、va_start、va_arg、va_end(va指代variable-argument)
例子
:
- #include <stdio.h>
- #include <stdarg.h>
- int sum(int n, ...);//第一个参数指定后面有多少个参数,省略号占位符表示数目不确定。
- int sum(int n, ...)//计算传入值的总和
- {
- int i,sum = 0;
- va_list vap;//va_list定义参数列表。
- va_start(vap, n);//va_start初始化参数列表。vap参数列表,n所有参数。
- for (i = 0; i < n; i++)
- {
- sum += va_arg(vap, int);//va_arg获取每一个参数的值。vap参数列表,int参数类型。
- }
- va_end(vap);//关闭参数列表。
- return sum;
- }
- int main()
- {
- int result;
- result = sum(3,2.5.9);
- printf("result = %d\n", result);
- return 0;
- }
内联函数:
多次循环调用函数的情况下,避免函数重复的去申请栈空间,而导致效率上的浪费。但增加了函数的编译时间。
在函数定义前加上关键字inline即可。
例:
#include <stdio.h>
inline int square(int x);
inline int square(int x)
{
return x * x;
}
int main(void)
{
int i = 1;
while (i <= 100)
{
printf("%d 的平方是%d\n", i-1, square(i++));
}
getchar();
return 0;
}
