首页 > 其他分享 >C语言——指针(字符指针、指针数组、数组指针、数组参数、指针参数)

C语言——指针(字符指针、指针数组、数组指针、数组参数、指针参数)

时间:2024-12-28 19:28:17浏览次数:7  
标签:arr int void 参数 数组 test 指针

文章目录

一、字符指针

  1. 一般的我们字符指针如下:将c的地址取出来放到p中去,指针p的类型是char*。
#include <stdio.h>
int main()
{
	char c = 'w';
	char* p = &c;
	printf("%c\n", *p);
	return 0;
}
  1. 还有另外一种,如下:将字符串首元素的地址存在p中,p的地址仍然是char*类型,当我们需要打印该字符串时就提供该字符串首元素的地址,然后就会打印出整个字符串。
#include <stdio.h>
int main()
{
	char* p = "hello";
	printf("%s\n", p);
	return 0;
}

注意,上述代码并不是将整个字符串“hello"放在了p中。
看下面一段代码。

#include <stdio.h>
int main()
{
	char str1[] = "hello";
	char str2[] = "hello";

	char* str3 = "hello";
	char* str4 = "hello";
	if (str1 == str2)
		printf("str1 == str2\n");
	else
		printf("str1 != str2\n");
	if (str3 == str4)
		printf("str3 == str4\n");
	else
		printf("str3 != str4\n");
	return 0;
}

我们创建了两个数组,因此会开辟两处不同的空间,数组名是首元素的地址,故str1 != str2,即使看上去它们两个存放了同样的内容;
接着对于str3、str4,它们两个存放了同一个字符串常量的首元素地址,故str3 == str4。
总结:C/C++会把常量字符串存储到单独的一个内存区域,当几个指针指向同一个字符串的时候,它们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。

二、指针数组

关于指针数组详见指针(1),下面简单解释几个例子:

int* arr1[10]; //在数组arr1中存放了10个int*类型的一级指针
char *arr2[4]; //在数组arr2中存放了4个char*类型的一级指针
char **arr3[5];//在数组arr3中存放了5个char**类型的二级指针

三、数组指针

1. 数组指针的创建与意义

简单来说数组指针就是存放数组的地址的指针变量,它是一个指针。
它所指向的是整个数组。
下面就是一个创建数组指针的例子:

#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int(*p)[10] = &arr;
	return 0;
}

int(*p)[10] = &arr;关于这个的解释如下:将数组arr的地址取出存放在p中,这时的p就是一个数组指针,它所指向的是整个数组,p的类型是int ( * )[10]。

下面我们就看看数组指针到底与数组名有什么不同:

#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int(*p)[10] = &arr;

	printf("%p\n", arr);
	printf("%p\n", arr + 1);

	printf("%p\n", p);
	printf("%p\n", p + 1);
	return 0;
}

结果如下
在这里插入图片描述
我们从第一个和第三个结果可以看出p与arr所储存的地址是一样的,都是数组首元素的地址,但当我们仔细分别观察第1,2个结果与第3,4个结果会发现,,当我们给arr+1后会跳过一个整型的内容,但给p+1时发现跳过了10个整型的内容,刚好就是数组arr的内容,这就让我们更加确信,虽然数组指针p与arr都储存了数组中首元素的地址,但数组指针p指向的是整个数组的内容,它们的意义截然不同。

2. 数组指针的使用

#include <stdio.h>
void Print(int(*p)[4], int r, int c)
{
	int  i = 0;
	for (i = 0; i < r; i++)//控制访问每个一维数组
	{
		int j = 0;
		for (j = 0; j < c; j++)//控制访问每一个一维数组中的每一个元素
		{
			printf("%d ", (*(p+i))[j]);
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][4] = { 1,2,3,4,2,3,4,5,3,4,5,6 };
	Print(arr, 3, 4);

	return 0;
}

在这段代码中,我们创建了一个二维数组arr,我们将arr当作一个数组指针传给了Print函数,当然了我们也是以一个类型为int ( * )[4]的数组指针p接收的,我们知道可以将二维数组看成由多个一维数组构成,每一个一维数组都是二维数组的一个元素,那么我们就可以利用循环来访问每一个一位数组(具体方法就是给数组指针p+1来跳过当前一维数组,访问下一个一维数组,其实就是实现了printf("%d ", (*(p+i))[j])),然后再借助循环来打印一维数组中的每个元素,这样其实就是利用数组指针打印了二维数组的每一个元素。

4.数组参数、指针参数

在写代码的时候难免要把【数组】或者【指针】传给函数,那函数的参数该如何设计呢?

1.一维数组传参

比如下面的代码,如何设计形参接收呢?

int main()
{
  int arr[10] = {0};
  int *arr2[20] = {0};
  test(arr); 
  test2(arr2);
}
  1. void test ( int arr[ ] ) : 对于通过test函数传了一维数组名,也就是一个数组,当然可以用数组接收,并且可以不指定大小。
  2. void test ( int arr[10] ):这与 1. 相同,只不过我了与数组的大小,并且大小与创建的数组一致。
  3. void test ( int *arr ):我们知道数组名是数组首元素的地址,并且这个地址指向的元素类型是int类型,那么我们就可以创建一个int * 类型的指针来接收。
  4. void test2 ( int *arr[20] ):对于int *arr2[20] = {0}数组传参,同样的道理我们可以用一个一致的数组来接收。
  5. void test2(int **arr):对于数组int *arr2[20] = {0},我们知道这是一个指针数组,当我们传过去数组名时我们就可以用一个二级指针来接收,原因是arr2表示数组中首元素的地址,而该数组是存放指针的数组,那么接收指针的地址就要用二级指针来接收。

2.二维数组传参

int main()
{
  int arr[3][5] = {0};
  test(arr);
}
  1. void test ( int arr [3][5] ):这是非常标准的接收,传过来数组,就用一致类型的数组来接收。
  2. void test ( int arr [ ][ ] ):这是标准的错误,我们在用数组接收实参时二维数组不能省略列数。
    例如,我们可以这样接收void test ( int arr [ ][5] )。
    总结:二维数组传参,函数形参的设计只能省略第一个 [ ] 的数字。
  3. 这样void test ( int arr )不能接收,因为二维数组的数组名代表二维数组中第一行的地址,也就是一个义务为数组的地址,表示一个数组指针,当然不能用一级指针来接收。
    这样void test ( int
    arr [5] )不能接收,形参部分是一个指针数组。
    这样void test ( int **arr )更不能接收,二维数组数组名代表一个一维数组的地址,是一个数组的的地址,根本上它是一个一级指针,当然不能用二级指针来接收了。
  4. 我们可以用一个数组指针来接收:void test ( int (*arr)[5] )。

标签:arr,int,void,参数,数组,test,指针
From: https://blog.csdn.net/shadoubuhuijiji/article/details/144743913

相关文章

  • cpp智能指针
      普通指针的不足new和new[]的内存需要用delete和deletel]释放。程序员的主观失误,忘了或漏了释放。程序员也不确定何时释放。普通指针的释放类内的指针,在析构函数中释放。C++内置数据类型,如何释放?new出来的类,本身如何释放?C++11新增三个智能指针类型uniqu......
  • 赋能现代菜田科学种植精准治理,基于YOLOv5全系列【n/s/m/l/x】参数模型开发构建农田种
    传统的农业种植场景下,甜菜等作物的管理模式通常依赖于大水漫灌和农药喷洒,这种作业方式不仅造成了水资源的严重浪费,还使得病虫害和杂草的治理完全依赖于菜农的经验。随着人工智能(AI)技术的快速发展,越来越多的传统行业开始探索将AI技术引入实际生产过程中,以提高效率、降低成本并实......
  • c语言书籍排序 多数组协同排序 按价格排序【书名同步】 带有空格的字符串读取
    题目:编写程序,从键盘输入n(n<10)本书的名称和定价并存入结构数组中,按单价从小到大排序并输出排序后的书籍信息。输入输出示例:括号内为说明,无需输入输出输入样例:3(n=3)ProgramminginC21.5ProgramminginVB18.5ProgramminginDelphi20输出样例:Programmingin......
  • 双指针
    [Algo]双指针1.接雨水//1.接雨水//https://leetcode.cn/problems/trapping-rain-water/inttrap1(vector<int>&height){vector<int>arr_l,arr_r;arr_l.resize(height.size());arr_r.resize(height.size());intlmax=INT32_MIN,rma......
  • java命令行参数与选项
    https://cloud.tencent.com/developer/article/1018405https://www.cnblogs.com/limeiyang/p/16565920.htmlhttps://cloud.tencent.com/developer/article/2363703https://www.cnblogs.com/xy14/p/11563830.htmlJava命令行参数用于启动Java程序,并可以通过这些参数来控制Ja......
  • 树状数组学习笔记
    树状数组概念\(a[i]\)数组存储当前序列数据\(s[i]\)用来存储区间和,其中下标i值代表的是一段区间,其区间长度取决于low_bit(i)例如:\(s[4]\),4对应二进制100,因此low_bit(i)=100,其长度为4,所以s[4]存储的为a[1]~a[4]的和。\(s[6]\),6对应二进制110,因此low_bit(i)=10,其长度为2,......
  • xdoj-指针类别 题目及参考答案
    目录写在前面220题目参考答案231题目参考答案232题目参考答案233题目参考答案235题目参考答案236题目参考答案237题目参考答案470题目参考答案536题目参考答案561题目参考答案660题目参考答案661题目参考答案662题目参考答案663题......
  • 写一个方法把如下字符串按运算符切割成数组`18x2÷9+1-6`
    在前端开发中,你可以使用JavaScript的String.prototype.split()方法和正则表达式来达到这个目的。由于你的字符串中包含多种运算符(x、÷、+、-),你可能需要使用一个稍微复杂的正则表达式来匹配这些运算符,并将字符串分割成数组。下面是一个示例函数,它接受一个字符串作为输入,并返回一......
  • 使用js实现一个与数组的forEach函数一样功能的函数
    在JavaScript中,forEach函数是Array的内置方法,用于遍历数组的每个元素并执行提供的函数。但是,如果你想自己实现一个与forEach功能相同的函数,可以这样做:functionmyForEach(array,callback,thisArg){//检查数组是否为数组类型,如果不是则抛出错误if(!Array.isArray(a......
  • 写个方法交换数组两个元素的位置
    在前端开发中,交换数组中两个元素的位置是一个常见的任务。你可以使用JavaScript的数组解构赋值来实现这个功能。下面是一个示例方法,它接受一个数组、第一个元素的索引和第二个元素的索引作为参数,并返回一个新的数组,其中这两个元素的位置已经交换:functionswapElements(arr,index......