首页 > 其他分享 >C语言指针(3)

C语言指针(3)

时间:2024-08-05 12:55:46浏览次数:14  
标签:return int C语言 add 数组 printf 指针

目录

一、字符指针变量

二、数组指针变量

三、⼆维数组传参的本质

四、函数指针变量

五、typedef 关键字

六、函数指针数组


一、字符指针变量

字符指针char*

&符号名  符号名,这都是获取的是首元素地址。

int main()
{
	char a[] = "abcdef";
	char* pc = &a;
	*pc = 'w';
	return 0;
}
//输出wbcdef

char* pc = &a;获取的只是字符串的首地址,并没有获取整个数组的地址。

int main ()
{
	const char* pstr = "hello bit.";
	printf("%s\n", pstr);
	return 0;
}

在这一行代码中,我们是否把hello bit整个字符串地址放入到pstr指针里面了吗?并没有,pstr只是获取了字符串中首元素的地址。

我们来分析以下题目,大家可以先思考。

int main()
{
	char str1[] = "hello bit.";
	char str2[] = "hello bit.";
	const char* str3 = "hello bit.";
	const char* str4 = "hello bit.";
	if (str1 == str2)
		printf("str1 and str2 are same\n");
	else
		printf("str1 and str2 are not same\n");
	if (str3 == str4)
		printf("str3 and str4 are same\n");
	else
		printf("str3 and str4 are not same\n");
	return 0;
}

这个题目是比较的地址是否相同。

str1与str2创建的变量不是在一个地址里面。

str3与str4因为是指针,这两个指针指向的是同一个字符串。

以上题目输出
str1 and str2 are not same

str3 and str4 are same

二、数组指针变量

指针获取的是指向类型变量的地址,指针需要获得整个数组的地址。

int* p1;//存放的是整型变量地址,能够指向整型数据的指针。

char* p2;//存放的是字符变量地址,能到指向字符数据的指针。

double* p3;//存放的是浮点型变脸的地址,能够指向浮点型数据的指针。

那么如何获取数组的地址并存放到指针里呢?

int main()
{
	int arr[5] = { 1,2,3,4,5 };
	int(*p)[5] = &arr;
	return 0;
}

在调试这段代码的时候,我们看见p已经接收了整个数组,数组的类型已经改变成int[5]*

三、⼆维数组传参的本质

void add(int arr[3][3], int r, int s)
{
	for (int i = 0; i < r; i++)
	{
		for (int j = 0; j < s; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}

int main()
{
	int arr[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
	add(arr, 3, 3);
	return 0;
}
//输出
1 2 3
4 5 6
7 8 9

我们以往想打印出二维数组是使用这种方法来实现打印的。

这是一个二维数组,二维数组是一个连续存放的数组,我可以把二维数组想成一条直线。

这一个3行5列的数组,arr[0]对应的是第一行首元素的地址,arr[1]对应的是第二行首元素的地址。

第一行数组指针类型是int (*)[5],每一行里有五个数

所以二维数组的本质也是传递了地址,传递的地址是一个每一行的数组地址。

void test(int(*p)[5], int r, int s)
{
	for (int i = 0; i < r; i++)
	{
		for (int j = 0; j < s; j++)
		{
			printf("%d ", (*(*p+i)+j));
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][5] = { {1,2,3,4,5}, {2,3,4,5,6},{3,4,5,6,7} };
	test(arr, 3, 5);
	return 0;
}
//输出
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7

void test(int* arr[5], int r, int s),每一行数组中元素的个数为5,使用int (*p)[5]是为了与二维数组‘arr’的每一行的结构匹配

四、函数指针变量

创建一个指针,指针指向的是一个函数。

int add(int x, int y)
{
	return x + y;
}

int main()
{
	int sz = add(3, 5);
	printf("%d\n", sz);
	return 0;
}

在以前我们都是直接把函数给传参过去。

int add(int x, int y)
{
	return x + y;
}

int main()
{
	int (*p)(int x, int y) = add;
	printf("%d\n", p(3,5));
	return 0;
}
//输出
8

int (*p)(int x, int y) = add;   p中存放了函数add的地址,我们就可以通过p直接使用add函数。

int (*)(int x, int y)
int (*)(int, int)
函数指针以上两种写法都可以,看函数需要什么类型的参数。
int add(int x, int y)
{
	return x + y;
}

int main()
{
	int (*p)(int x, int y) = add;
	printf("%d\n", p(3,5));
	printf("%d\n", (*p)(4, 6));
	return 0;
}
//输出
8   
10

以下两种写法都是可以的,推荐使用第一种写法,看起来比较清晰
printf("%d\n", p(3,5));
printf("%d\n", (*p)(4, 6));

五、typedef 关键字

typedef可以讲类型重命名,可以把复杂类型简化成简单。

typedef unsigned int uint;

int main()
{
	unsigned int a = 10;
	uint b = 30;
	return;
}
在这段代码中,把unsigned int给重命名uint。

可以把int*给重命名
typedef int* test;

int(*)[5]也可以给重命名
typedef int(*add)[10];
我们给重命名add,在数组指针里,我们需要在*的右边命名。

int (*)(int,int)同样也能重命名
typedef int(*fun)(int,int);
把int (*)(int,int)给重命名了fun,函数指针跟数组指针一样,都要把重新命名的名字写在*旁边

六、函数指针数组

函数指针数组是把指向函数的指针放一个数组里面里面,创建一个指针指向这个数组。

int add(int x, int t)
{
	return x + y;
}

int sub(int x, int t)
{
	return x - y;
}

int mul(int x, int t)
{
	return x * y;
}

int div(int x, int t)
{
	return x / y;
}

int main()
{
	int (*p[5])(int, int) = { add,sub,mul,div };
	return 0;
}


int (*p[5])(int, int) = { add,sub,mul,div };这一行代码就是函数指针数组,使用了我们前面学习的函数指针,指针数组,

标签:return,int,C语言,add,数组,printf,指针
From: https://blog.csdn.net/m0_62048999/article/details/140923943

相关文章

  • C语言指针(1)
    目录一、内存和地址1、生活中的例子2、内存的关系二、指针变量和地址1、&符号,%p占位符2、一个简单的指针代码。3、理解指针4、解引用操作符5、指针变量的大小。三、指针变量类型的意义1、指针解引用的作用2、指针+指针3、指针-指针4、void*指针四、const修饰指......
  • C语言--轮圈机制
    数据是以二进制补码形式存储在计算机内存中,而数据类型限制了数据的大小,种类,范围,精度等。在存储二进制数据时,常常遇到存储的数值超出数据类型范围的情况。而这时的存储原理又是怎样的呢?根据实践,不难总结出一个规律,计算机存储的数据在一个范围内循环。如下图所示。有符号和无符......
  • 模拟实现 memmove --浅谈C语言
    内存移动-memmove也是拷贝函数,源字符串可能会被覆盖,但保证目标是想要的描述C库函数void*memmove(void*str1,constvoid*str2,size_tn)从str2复制n个字符到str1,但是在重叠内存块这方面,memmove()是比memcpy()更安全的方法。如果目标区域和源区域有重叠的......
  • C++ 指针注意事项总结
    在C++中,指针是一种强大的工具,允许程序员直接访问和操作内存地址。然而,由于指针直接操作内存,错误的使用可能导致程序崩溃、内存泄漏等严重问题。以下是C++指针相关的详细注意事项:1.指针初始化定义指针时务必初始化:未初始化的指针可能指向任意内存地址,称为“野指针”。野指......
  • 嵌入式学习第15天——C语言二维数组、字符数组
    二维数组定义二维数组本质上是一个行列式的组合,也就是说二维数组是有行和列两部分构成。二维数组数据是通过行列进行解读。二维数组可被视为一个特殊的一维数组,相当于二维数组又是一个一维数组,只不过它的元素是一维数组。语法 类型数组名[行数][列数]举例: intarr[3]......
  • 【C语言】《C语言基础指南!》- 史上最全!
    目录C语言基础精讲1.C语言简介1.1.C语言的历史1.2.C语言概述1.3.C语言的特点2.基本语法2.1.程序结构2.2.数据类型3.变量和常量3.1.变量声明与初始化3.2.常量定义4.控制结构4.1.条件语句4.2.循环语句5.函数5.1.函数定义5.2.函数调用6.数组和字符串......
  • c语言数据结构单链表中随机链表的复制
    c语言数据结构单链表中随机链表的复制文章目录c语言数据结构单链表中随机链表的复制1.随机链表的复制问题2.解决思路3.代码的实现1.随机链表的复制问题给你一个长度为nn......
  • 模拟实现 strstr(字符串查找) --浅谈C语言
    C字符串查找-strstr()描述C库函数char*strstr(constchar*haystack,constchar*needle)在字符串haystack中查找第一次出现字符串needle的位置,不包含终止符'\0'。声明下面是strstr()函数的声明。char*strstr(constchar*haystack,constchar*needle)参......
  • C语言学习----常用函数
    1.输入输出:scanf输入printf输出格式:scanf("格式控制符",变量的地址);printf(“格式控制符”,变量);注意变量的地址和变量不同,变量的地址用取址符&加变量名组成例如&a;inta;scanf("%d",&a);printf("%d",a);这段代码会要求从控制台输入一个整数,然后输出它。格式控制......
  • C语言零基础学习笔记12——数组(一)
    本节大纲一、数组的概念二、一维数组的创建和初始化三、一维数组的使用四、一维数组在内存中的储存五、sizeof计算数组元素个数一、数组的概念        数组的概念是一组相同类型元素的集合;从这个概念中我们就可以发现2个有价值的信息:1、数组中存放的是1个......