(二)数组、指针、函数

一、数组

    1、一维数组

        1》定义

        2》初始化

        3》使用

        4》存储

    2、多维数组

        1》定义

        2》初始化

        3》使用

        4》存储

    3、变长数组

    4、数组传参

        地址传递:传数组名和元素个数

#include <stdio.h>

//void fun(int n,int b[])
void fun(int n,int *b)
{
	int i;
	for(i = 0; i < n; i++)
		printf("%d\t",b[i]);
	printf("\n");
}

int main(void)
{
	int a[5] = {1,2,3,4,5};


	fun(5,a);
	return 0;
}

#include <stdio.h>

//void fun(int n,int m, b[][m])
void fun(int n,int m, int (*b)[m])
{
	int i,j;
	for(i = 0; i < n; i++){
		for(j = 0; j < m; j++)
			printf("%d\t",b[i][j]);
		printf("\n");
	}
}

int main(void)
{
	int a[2][3] = {{1,2,3},{4,5,6}};

	fun(2,3,a);
	return 0;
}

二、指针

    1、概念:

在C语言中,内存单元的地址称为指针,专门用来存放地址的变量,称为指针变量(pointervariable), 在不影响理解的情况中,有时对地址指针指针变量不区分,通称指针

    2、指针三要素:

       当给一个指针初始化或者赋值之后,则该指针存在三要素,例如:

           int a = 100;

           int *pa = &a;

       此时,对于pa来说,有以下三个表达式:

           *p  表示p指向的数据

           p   表示p的内容

           &p  表示变量p在内存中的地址

    3、指针的运算:

       1》赋值: =

       2》取值:*

       3》取地址:&

       4》加法运算:+

            只能加一个整数

       5》减法运算:-

            可以减一个整数

            也可以两个同类型的指针相减

        6》关系运算:> < >= <= == !=

            表示地址高低的比较

    4、const关键字

    5、多级指针

        在C语言中,把存储指针变量地址的变量,称为多级指针变量,简称多级指针。

        int a = 100;

        int *p1 = &a;    //p1为一级指针

        int**p2  = &p1; //p2为二级指针

        int ***p3 = &p2; //p3为三级指针

        综上:n级指针变量中可以存放n-1级指针变量的地址。

#include <stdio.h>


int main(void)
{
	int a = 100;
	int *p1 = &a;  		//p1为一级指针
	int **p2  = &p1;	//p2为二级指针
	int ***p3 = &p2;	//p3为三级指针
	
	printf("a = %d\n",a);
	printf("*p1 = %d\n",*p1);
	printf("**p2 = %d\n",**p2);
	printf("***p3 = %d\n",***p3);
	return 0;
}


6、void关键字

        1》修饰函数返回值

            表示该函数没有返回值

        2》修饰函数的参数

            表示该函数没有参数

        3》定义指针

            表示该指针中可以存放任何类型的地址,通常我把它称为通用指针。

#include <stdio.h>


int main(void)
{
	void *p;

	int a = 100;
	p = &a;
	printf("a : %d\n",a);
	printf("*p : %d\n",*(int*)p);

	char b = 'A';
	p = &b;
	printf("b : %c\n",b);
	printf("*p : %c\n",*(char*)p);

	float c = 3.4;
	p = &c;
	printf("c : %f\n",c);
	printf("*p : %f\n",*(float*)p);
	return 0;
}

三、指针和数组的关系:

    1、指针可以指向一个数组,数组指针

    2、数组中可以存储多个相同类型的地址,指针数组

#include <stdio.h>

int main(void)
{
#if 1
	int a[5] = {1,2,3,4,5};
	int *b[5] = {a,a+1,a+2,a+3,a+4};
	int *p = a;
	int * *pb = b;
	int i;

	for(i = 0; i < 5; i++)
		printf("%d\t%d\n",p[i],*(p+i));

	for(i = 0; i < 5; i++)
		printf("%d\t",*pb[i]);
	printf("\n");
#else
	int a[2][3] = {{1,2,3},{4,5,6}};
	int(*p)[3] = a;
	int i,j;

	for(i = 0; i < 2; i++)
		for(j = 0; j < 3; j++)
			printf("%d\t%d\t%d\n",p[i][j],*(p[i]+j),*(*(p+i)+j));
#endif

	return 0;
}

3、带参的主函数

#include <stdio.h>

/**
 	argc : 命令行参数个数
	argv : 命令行参数

 */
//int main(int argc, char *argv[])
int main(int argc, char **argv)
{
	int i;

	printf("argc = %d\n",argc);
	for(i = 0; i < argc; i++)
		printf("%s\n",argv[i]);
	return 0;
}

四、函数

    1、基本概念

        1》函数的定义

        2》函数的声明

        3》函数的调用

        4》实参,形参及它们的关系

    2、函数传参

        1》传参方式:

            1)值传递:

                在被调用函数中不能改变实参

                实参类型和形参类型相同

            2)地址传递

                在被调用函数中可以改变实参

                形参类型是实参类型对应的指针类型

        2》根据实参的类型可以将传参分为以下几种

            1)实参是常量

                值传递

            2)实参是基本类型变量

                值传递

                地址传递

            3)实参是数组

                地址传递:传数组名和元素个数

            4)实参是指针变量

                值传递:

#include <stdio.h>

void fun1(int *p1,int *p2)
{
	int *t,b;
	//不能改变实参的值
	t = p1;
	p1 = p2;
	p2 = t;

	//可以改变实参指向的数据
	b = *p1;
	*p1 = *p2;
	*p2 = b;


}

void fun2(int **p1,int **p2)
{
#if 0
	int *t;
	//可以改变实参的值
	t = *p1;
	*p1 = *p2;
	*p2 = t;
#else
	//实参指向的数据也可义改变
	int b;
	b = **p1;
	**p1 = **p2;
	**p2 = b;

#endif
}
int main(int argc, char **argv)
{
	int a = 3,b = 5;
	int *pa = &a, *pb = &b;

#if 0
	printf("pa = %p,pb = %p\n",pa,pb);
	printf("a = %d\t,b = %d\n",a,b);
	fun1(pa,pb);  //值传递,在被调用函数中不能改变pa和pb
	printf("pa = %p,pb = %p\n",pa,pb);
	printf("a = %d\t,b = %d\n",a,b);
#endif
#if 1
	printf("pa = %p,pb = %p\n",pa,pb);
	printf("a = %d\t,b = %d\n",a,b);
	fun2(&pa,&pb);//地址传递,在被调用函数中可以改变pa和pb
	printf("pa = %p,pb = %p\n",pa,pb);
	printf("a = %d\t,b = %d\n",a,b);
#endif
	return 0;
}

3) 返回函数的地址

4)返回值字符型指针

#include <stdio.h>

int fun1(void)
{
	int x = 123;
	return x;
}

char * fun2(void)
{
	return "hello world";
}

int *fun3(int n,int a[])
{
	int i;
	for(i = 0; i < n; i++)
		a[i] *= 2;

	return a;
}

void fun(void)
{
	printf("hello world\n");
}

typedef void(*TYPE)(void);

//void(*fun4(void))(void)
TYPE fun4(void)
{
	return fun;
}


char *fun5(void)
{
	//char p[] = "hello world";   //p不能返回
	char *p = "hello world";	//p可以返回
	return p;
}

int main(int argc, char **argv)
{
#if 1
	char *str;
	str = fun5();
	printf("%s\n",str);
#else
	void (*p)(void);
	p = fun4();
	p();
	int arr[5] = {1,2,3,4,5};
	int *p,i;
	
	for(i = 0; i < 5; i++)
		printf("%d\t",arr[i]);
	printf("\n");
	p = fun3(5,arr);
	for(i = 0; i < 5; i++)
		printf("%d\t",arr[i]);
	printf("\n");
#endif
	return 0;
}

通用行Makefile,在当前目录下需要生成多个可执行文件是直接make,同时根据时间戳分别一一生成对应文件名的可执行文件

CC = gcc
CFLAGS = -Wall -g -O0

#wildcard 执行make时,将当前目录下所有*.c的文件名赋给SRC
SRC = ${wildcard *.c}

#patsubst 根据第一个参数,在第三个参数中匹配对应的文件名,匹配成功则将其转换成第二个参数的格式
OBJS = ${patsubst %.c,%,$(SRC)}



#all为伪目标
all:$(OBJS)

%:%.c
	$(CC) -o $@ $^
     
clean:
	$(RM) $(OBJS)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值