C语言 指针基础篇 数组,函数与指针的运用 2 14
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C语言 指针基础篇 数组,函数与指针的运用 2 14,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含8767字,纯文字阅读大概需要13分钟。
内容图文
下面看看如何在函数中运用指针吧
下面是往函数传入指针的简单操作,不是传入数组的。判断一个a是否大于b是的话给,是的话对其进行操作,不是的话就直接返回。
1 #include <stdio.h> 2int main(){ 3int num1,num2,*p1,*p2; 4 p1 = &num1,p2=&num2; 5 scanf("%d%d",&num1,&num2); 6 7int fun(int *n1,int *n2); //我们在声明函数时候,要定义好“指针变量” 8if(*p1<*p2){ 9 fun(p1,p2); //而在传入值的时候只需要把指针变量传入进去就行了,这里没有*是因为指针变量值需要在声明的时候加*10 } 11 printf("max num is:%d\nmin mum is:%d",*p1,*p2); //这里的*P就是解引用的操作12return0; 13} 14int fun(int *n1,int *n2){ //声明的指针变量和定义的指针变量的名字必须相同15int tmp; 16 tmp = *n1; 17 *n1 = *n2; 18 *n2 = tmp; 19return0; 20 }
下面是函数中在运用传入指针的时候的错误操作
错误1:
1 int fun(int *n1,int *n2){ 2int tmp; 3 tmp = n1; 4 n1 = n2; 5 n2 = tmp; 6return0; 7 }
原因:不能达到预期结果,因为这只交换了p1和p2的值,只是交换了他们的储存空间,没有交换内容。并且本身修改后不能传回实参,即不能传到main函数,最直接的就是编译器会直接报错。
错误2:
1 int fun(int *n1,int *n2){ 2int tmp*; 3 tmp* = *n1; 4 *n1 = *n2; 5 *n2 = *tmp; 6return0; 7 }
原因:上述方式,定义了一个未知空间temp,并且通过指针修改了其数据。如果temp中存的是非常重要的内容,那么程序就会出问题,所以这种方法也是非常不可取的。但是编译的时候是不会报错的。
错误3:
1 int fun(int n1,int n2){ 2int tmp; 3 tmp = n1; 4 n1 = n2; 5 n2 = tmp; 6return0; 7 }
原因:能传递,但是不能输出交换后的值。
错误4:
1 int fun(int *n1,int *n2){ 2int tmp; 3 tmp = n1; 4 n1 = n2; 5 n2 = tmp; 6return0; 7 }
原因:这样根本就没有调用到传入的值,所以也不会进行操作。
1 #include <stdio.h> 2int main(){ 3int num1,num2,*p1,*p2; 4 p1 = &num1,p2=&num2; 5 scanf("%d%d",&num1,&num2); 6 7int fun(int *n1,int *n2); 8if(*p1<*p2){ 9 fun(p1,p2); 10 } 11 printf("max num is:%d\nmin mum is:%d",*p1,*p2); //这里取的是经过函数操作后的p1和p2,并没有用返回值。12return0; 13} 14int fun(int *n1,int *n2){ 15int tmp; 16 tmp = n1; 17 n1 = n2; 18 n2 = tmp; 19return0; 20 }
而在上面你也可以看到,我们并没有取返回值。但是我们可以获取到经过函数操作后的结果。
我们再弄一个例子,输入三个数。按照大小排列。用指针的方式实现:
1 #include <stdio.h> 2int main(){ 3int a,b,c,*p1,*p2,*p3; 4 printf("Please input two num:"); 5 p1 = &a,p2=&b,p3=&c; 6 scanf("%d %d %d",&a,&b,&c); 7int pd(int *num1,int *num2,int *num3); 8 pd(p1,p2,p3); 9 printf("%d>%d>%d",*p1,*p2,*p3); 10return0; 11} 12int pd(int *num1,int *num2,int *num3){ 13int lj(int *n1,int *n2); 14int i; 15for (int i = 0; i <3 ; ++i) { 16if (*num1 < *num2) { 17 lj(num1, num2); 18 } elseif (*num1 < *num3) { 19 lj(num1, num3); 20 } elseif (*num2 < *num3) { 21 lj(num2, num3); 22 } 23 } 24return0; 25} 26int lj(int *n1,int *n2){ 27int tmp; 28 tmp = *n1; 29 *n1 = *n2; 30 *n2 = tmp; 31return0; 32} 33//这个代码有两个要点: 34//1,他们的都是靠指针进行返回的,也就是说可以返回多个值 35//2,在进行逻辑的判断或其他的操作的时候就把指针转换成值,如果是函数进行传值的话就用指针进行传递。
把指针作为函数的返回值
方法:1,定义函数的时候类型定义成指针类型。2,返回值是一个地址。
如下例子:
1 #include <stdio.h> 2int main(){ 3char str[] = "luotianyi"; 4 5char* found(char* str,char ch); 6char* p = found(str,‘i‘); 7if (p == NULL){ 8 printf("没有此字符\n"); 9 } 10else{ 11 printf("输出此字符:%s\n",p); //输出字符串,因为数组的名字是数组的首地址,又因为是地址。所以不需要加上“&”所以也不需要加上“*”。只有字符串才可以,字符不行。 12 } 13return0; 14} 15//我们先定义函数的类型是指针类型16char* found(char* str,char ch){ //这里的括号里面的char后面要加上“*”是因为我们在声明和定义的时候没有说str是一个数组,因此只能通过 17//“*”把传入的首地址转换为其元素的值,我们才能在下面对其进行操作。如果把声明和定义换成:char str []也是可以的18int i=0; 19while (str[i]){ 20if (str[i] == ch){ 21return &str[i]; //把需要的值进行返回的值的地址进行返回。22 } 23 i++; 24 } 25return NULL; 26 }
上面的里面的判断使用数组进行的,而我们可以用指针进行判断。
如下例子:
1 #include <stdio.h> 2int main(){ 3char str[] = "luotianyi"; 4char* found(char* str,char ch); 5char* p = found(str,‘i‘); 6if (p == NULL){ 7 printf("没有此字符\n"); 8 } 9else{ 10 printf("输出此字符:%s\n",p); //输出字符串,以为数组名是数组的首地址。因此不需要加上“&”所以在获取的时候也不需要加上“*”。只有字符串才可以,字符不行。 11 } 12return0; 13} 14//我们把声明的类型换成是指针类型15char* found(char* str,char ch){ //这里的括号里面的char后面要加上“*”是因为我们在声明和定义的时候没有说str是一个数组,因此只能通过 16//“*”把传入的首地址转换为其元素的值,我们才能在下面对其进行操作。如果把声明和定义换成:char str []也是可以的17while (*str){ //这里的“*”就是获取指针的值,其实与str[i]是一样的18if (*str == ch){ 19return str; //这里的str在传入的时候就已经规定是指针的类型了,因此不需要再次*20 } 21 str++; //对指针的自加操作22 } 23return NULL; 24 }
下面是数组如何运用指针的
数组的地址其实是这样的,例如:int a[2] = {0,1,2};这样的话其实在内存中是对其每一个元素都开辟了一个地址的,假设第一个元素的地址是101,第二个是105,第三个就是这是因为:1,int本身就占4个字节,每一个int的元素也是占4个字节。2,数组的地址是具有连贯性的,是一个接着一个的。3,我么可以通过指针的偏移来取出一个个数组的内容。而这个的数组的地址,其实就是第一个元素的地址。下面就让我们来一个个的证明这些观点
数组的地址就是数组第一个元素的地址
1 #include <stdio.h> 2int main() 3{ 4int sz[] = {1,2,3,4}; 5 printf("%p\n",&sz); //取整个数组的地址 6 printf("%p\n",&sz[0]); //取第一个元素地址 7return0; 8} 9//输出结果: 10//0xffffcc10 11//0xffffcc10
每一个元素占4个字节,数组的地址具有连贯性
1 #include <stdio.h> 2int main() 3{ 4int sz[] = {1,2,3,4}; 5 printf("%ld\n",&sz[0]); 6 printf("%ld\n",&sz[1]); 7 printf("%ld\n",&sz[2]); 8 printf("%ld\n",&sz[3]); 910return0; 11} 12//这里本来应该是用%p输出地址的,%p输出的是16进制的。但是为了方便看改正了%lp13/*14 * 输出结果 15 *4294954000 16 *4294954004 17 *4294954008 18 *4294954012 19*/
看看如何通过指针的偏移,进行调用
1 #include <stdio.h> 2int main() 3{ 4int sz[] = {1,2,3,4}; 5int *p = &sz[0]; 6 printf("%d\n",*(p+1)); 7 printf("%d\n",*(p+2)); 8return0; 9 }
下面我们来看一个如何用指针运用数组
1 #include <stdio.h> 2int main() 3{ 4int sz[] = {1,2,3,4}; 5int *p; //把数组的首字符给了指针p 6int num =0; 7for (p = &sz[0];p<=&sz[3];p++){ //在这里我们的循环是用地址来定义的,这里直接定义成&sz也可以,但是有警告 8 num = num + *p; //而我们也可以用地址来获取到对应的值 9 } 10 printf("num : %d",num); 11return0; 12 }
下面总结下,有三种方法访问数组;
1,下标法
1 #include <stdio.h> 2int main() { 3int num[] = {0,1,2,3,4,5,6,7,8,9}; 4for(int i=1;i<10;i++){ 5 printf("%d\n",num[i]); 6 } 7return0; 8 }
2,通过数组名字获取到期地址,找出地址的值。
1 #include <stdio.h> 2int main() { 3int num[] = {0,1,2,3,4,5,6,7,8,9}; 4 printf("%ld\n",num); //这里可以看出,我们直接访问这个数组的话是直接访问到地址的:4294953968为了 5// 方便我们用长整型的方法输出 6for (int i = 0; i < 10; ++i) { 7 printf("%d\n",*(num+i)); //因为上面直接访问了 数组名字得到的是地址,所以我们直接在数组前面加上*就可以 8// 直接找到地址所对应的值 9//这里加i实际上因为类型的原因是每次加上四个字节10 } 11return0; 12 }
3,用指针变量通过指针的偏移而找到值。
1 #include <stdio.h> 2int main() { 3int num[] = {0,1,2,3,4,5,6,7,8,9}; 4int *p = &num[0]; 5for(int i=0 ;i<10;i++,p++){ 6 printf("%d\n",*p); 7 } 8return0; 9 }
数组的指针偏移1表示指针往右边移动了一个类型,例如:int的类型加1等于指针地址加上了4个字节。
指针通过循环输出了数组所有的元素,然后指针本身就变成了一个野指针。我们可以通过过:野指针-数组名 =数组的个数(也可以说是指针的偏移量)
函数传入数组
数组做函数参数,说具体是指向数组的指针变量做函数参数。
由于数组名是该数组的首地址,指针变量的值也是首地址,所以函数的实参和形参都可以指向数组名或者数组的指针。于是有了以下四种对应关系:
例子:
1 #include <stdio.h> 2int main() 3{ 4float ave(int *b, float num); //这里的是声明函数 5int counter,a[5] = {0}; 6float all =0, res; 7 8 scanf("%f", &all); 9for(counter = 0; counter < all; counter++) 10 { 11 scanf("%d", &a[counter]); 12 } 13 res = ave(a, all); //这里把数组的名字传入了函数定义的指针变量。和输入第一次输入的次数14 printf("%f", res); 15return0; 16} 1718float ave(int *b, float num) //这里和上面声明函数一样19{ 20int i, sum =0; 21float ave; 22for(i = 0; i < num; i++) 23 { 24 sum = sum + b[i]; 25 } 26 ave = (float)sum/num; 27return ave; 28 }
这里传入函数ave的是数组a的首地址,而不是将整个数组传入。传入首地址后,ave函数就按照一定顺序去访问a的储存空间,从而得到a中的数据。
当然float ave(int *b, float num) 也可以写为float ave(int b[], float num) 或者float ave(int b[100], float num) 也就是说b[] 后面方括号内可以是任意数字,因为那个数字是没有意义的,真真起作用的是b和方括号。
总结一下这部分就是:
数组做形参,其实就是指针做形参。只要指针向函数内传入数组首地址,那么函数形参和实参是指同一数组。函数内部对数组所做的处理,就是对主调函数中的实参数组所作的处理,可以传回主调函数。
指针和字符串与函数
f(int arr[ ] ,int n)但是在编译时是将arr按指针变量处理的,相当于将函数 f 的首部写成 f ( int* arr,int n)。这两种写法是等价的,而%s的输出可以是字符串的地址,而不需要解引用。
输出字符串有三种方法,如下所示。
1 #include <stdio.h> 2int main(){ 3char ch1[] ="luotianyi"; //第一种是用数组的方式输出字符串4 printf("%s\n",ch1); 5char *ch2 = "luotianyi"; //第二种是利用指针变量保存字符串6 printf("%s\n",ch2); 7 printf("luotianyi"); //第三种是直接用把字符串放到printf中8return0; 9 }
这三种方法有2个区别,第一种利用数组的方式存储是把字符串存储在栈中(也就是可以进行修改的地方,也可以进行输出)。第二种和第三种是保存在堆中的(也就是只能输出,但是不允许进行修改)。
1 #include <stdio.h> 2int main(){ 3char ch1[] ="luotianyi"; 4 ch1[1] = ‘w‘; //可以进行修改 5 printf("%s\n",ch1); 6char *ch2 = "luotianyi"; 7 *ch2+1 = ‘s‘; //error: lvalue required as left operand of assignment 8 printf("%s\n",ch2); 9 printf("luotianyi"); 10return0; 11 }
下面我们看看字符串是如何传入函数中的,我们分别演示下用指针变量和数组变量进行。
1 #include <stdio.h> 2int main(){ 3char str1[] = "luotianyi"; 4char* str2 = "my wife"; 5int strpri(char ch1[],char* ch2) ; 6 strpri(str1,str2); 7return0; 8} 9int strpri(char ch1[],char* ch2){ //我们分别用两种方法传入10char* tmp; //创建一个指针对其进行转换11 tmp = ch1; 12 ch1 = ch2; 13 ch2 = tmp; 14 ch2[3] = ‘z‘; 15 printf("%s\n",ch1); //在这里可以看出指针变量所指向的字符串内部虽然不可以改变,但是可以对其整体进行其他的操作。 16//也就是说字符串单个字符的操作是不可以的,但是可以对其整体进行操作17 printf("%s\n",ch2); //这里可以看出我们可以对数组变量的字符串进行操作18return0; 19 }
堆与栈的区别还有就是栈可以保存多份一样的值,而堆只保存一份,其余的也要调用的话就是多个变量都是指向堆的这一份。
1 #include <stdio.h> 2int main(){ 3char* a = "luotianyi"; 4char* b = "luotianyi"; 5 printf("%ld\n",a); 6 printf("%ld\n",b); 7return0; 8} 9/*10 * 4299173896 11 * 4299173896 12 * */
指针字符串 or 数组字符串
1 #include <stdio.h> 2int main(){ 3char* ch[] = {"luotianyi","wsj","woaini"}; //这就是创建一个数组字符串或是叫做指针字符串 4for (int i = 0; i < 3; ++i) { 5 printf("%s\n",ch[i]); //输出全部 6 } 7 printf("%c\n",ch[1][2]); //第一个下标是第几排,第二个是低级列 8 printf("%c\n",*(*(ch+1)+1)); //外面的数字是第几横排,里面的是横排的第几个数字 9return0; 10 }
---------------------
部分来源和代码出自以下链接
来源:CSDN
原文:https://blog.csdn.net/C2681595858/article/details/53750577
版权声明:本文为博主原创文章,转载请附上博文链接!
原文:https://www.cnblogs.com/luotianyi520/p/9862292.html
内容总结
以上是互联网集市为您收集整理的C语言 指针基础篇 数组,函数与指针的运用 2 14全部内容,希望文章能够帮你解决C语言 指针基础篇 数组,函数与指针的运用 2 14所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。