C语言——数组、指针、函数

一.数组。

含义:存储一些同类型数据的地方,数组是一块连续的内存地址。
数组名代表这块地址的起始地址。

即:

#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


d.指定初始化元素。


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内变量名可以一样,其是作用域。)
函数调用:函数名(传入参数);
  1. #include <stdio.h>  
  2.    
  3. /* 函数声明 */  
  4. int max(int num1, int num2);  
  5.    
  6. int main ()  
  7. {  
  8.    /* 局部变量定义 */  
  9.    int a = 100;  
  10.    int b = 200;  
  11.    int ret;  
  12.    
  13.    /* 调用函数来获取最大值 */  
  14.    ret = max(a, b);        //传入的参数被称为实参,实际参数。  
  15.    
  16.    printf( "Max value is : %d\n", ret );  
  17.    
  18.    return 0;  
  19. }  
  20.    
  21. /* 函数返回两个数中较大的那个数 */  
  22. int max(int num1, int num2)     //如果将函数的定义放在main函数之前可以省略函数的声明。这里的参数被称之为形参,形式参数  
  23. {  
  24.    /* 局部变量声明 */  
  25.    int result;  
  26.    
  27.    if (num1 > num2)  
  28.       result = num1;  
  29.    else  
  30.       result = num2;  
  31.    
  32.    return result;     //当函数执行到return时函数结束返回其必有的返回值。  
  33. }  
参数
a.形参与实参
形参:函数定义时所用的参数。
实参:函数调用时传入的参数。
b.传值与传址
传值与传址的区别在于可以改变其原有数据的值。传址用指针、数组,传值用变量。
c.可变参数(函数参数的传入是可变的)
预备知识:需要使用头文件stdarg.h、内的va_list、va_start、va_arg、va_end(va指代variable-argument)
例子:
  1. #include <stdio.h>  
  2. #include <stdarg.h>  
  3.   
  4. int sum(int n, ...);//第一个参数指定后面有多少个参数,省略号占位符表示数目不确定。  
  5.   
  6. int sum(int n, ...)//计算传入值的总和  
  7. {  
  8.  int i,sum = 0;  
  9.  va_list vap;//va_list定义参数列表。  
  10.  va_start(vap, n);//va_start初始化参数列表。vap参数列表,n所有参数。  
  11.  for (i = 0; i < n; i++)  
  12.  {  
  13.   sum += va_arg(vap, int);//va_arg获取每一个参数的值。vap参数列表,int参数类型。  
  14.  }  
  15.  va_end(vap);//关闭参数列表。  
  16.  return sum;  
  17. }  
  18. int main()  
  19. {  
  20.  int result;  
  21.    
  22.  result = sum(3,2.5.9);   
  23.  printf("result = %d\n", result);  
  24.    
  25.  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;
}



阅读更多
换一批

没有更多推荐了,返回首页