OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5524|回复: 6

分享:新手如何学好C语言-指针

[复制链接]

70

主题

119

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
433
金钱
433
注册时间
2013-8-19
在线时间
2 小时
发表于 2014-12-5 15:23:24 | 显示全部楼层 |阅读模式



 复习运算符
(关系运算与逻辑运算)

#include "stdio.h"

void main()

{

  int a=1,b=2,m=0,n=0,k;printf("%d\n",m);

  k=(n=b>a)||(m=a<b); printf("%d\n",m);

  printf("%d,%d\n",k,m);

}

(条件运算,与逗号运算)

#include "stdio.h"

void main()

{

 char a=1,b=3,c=0;   

 printf("%d",(a+b>a-b?a++:++b,++a,b+5));

}//%d 整形输出  %c 字符  %s 字符串 %f 浮点

复习函数(带形参的返回函数值可以做判断语句的条件)

#include “stdio.h”

char delay(char t);

char delay(char t)  //t=3

{

t++;   //t=4

return t;

}

void main()

{

char i=8,k;

 if(i>delay(2))

 {

  k=delay(3);  //k=4

  i++;    //i=9

  printf("k=%d,i=%d",k,i);

  }   

}

复习全局变量做形参其值不变

#include "stdio.h"

void delay(int y);

int y=3;

void delay(int y)  //y=5

{

  for(;y<6;y++);

  printf("y1=%d\n",y);  //y=6



void main()

{

int  mm;

delay(5);

printf("y2=%d\n",y); //y=3

mm=y++;  //mn=3,y=4

printf("y3=%d\n",y);

指针数组(里面存放的是指针,如果是字符串则存放的是字符串的首地址)

#include "stdio.h"

void main()

{

char i=0,*p[3]={"wejlj","dsag","dsfads"} ;  

for(;i<3;i++)

{

printf("%c \n",*(p));

}

}

#include "stdio.h"

main(){

int a[3][3]={1,2,3,4,5,6,7,8,9};

int *pa[3]={a[0],a[1],a[2]};

int *p=a[0];

  int i;

  for(i=0;i<3;i++)

      printf("%d,%d,%d\n",a[2-i],*a,*(*(a+i)+i));

  for(i=0;i<3;i++)

      printf("%d,%d,%d\n",*pa,p,*(p+i));

}

指针函数与函数指针的区别

1、指针函数是指带指针的函数,即本质是一个函数。函数返回类型是某一类型的指针

类型标识符 *函数名(类型 参数表)

int *f(int x,int y);

首先它是一个函数,只不过这个函数的返回值是一个地址值。函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量。

表示:

float *fun();

float *p;

p = fun(a);

注意指针函数与函数指针表示方法的不同,千万不要混淆。最简单的辨别方式就是看函数名前面的指针*号有没有被括号()包含,如果被包含就是函数指针,反之则是指针函数。

来讲详细一些吧!请看下面

指针函数:
当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需要指针或地址的表达式中。
格式:
类型说明符 * 函数名(参数)
当然了,由于返回的是一个地址,所以类型说明符一般都是int。
例如:int *GetDate(void);
int * aaa(int,int);
函数返回的是一个地址值,经常使用在返回数组的某一元素地址上。

#include "stdio.h"

int * GetDate(int wk,int dy);

main()

{

int wk,dy;

do

{

printf("Enter week(1-5)day(1-7)\n");

scanf("%d%d",&wk,&dy);

}

while(wk<1||wk>5||dy<1||dy>7);  // wk=2;dy=3

printf("%d\n",*GetDate(wk,dy));

}

int * GetDate(int wk,int dy)

{

static int calendar[5][7]=

{

{1,2,3,4,5,6,7},

{8,9,10,11,12,13,14},

{15,16,17,18,19,20,21},

{22,23,24,25,26,27,28},

{29,30,31,-1}

}; //不释放空间

return &calendar[wk-1][dy-1]; //1,2

}
程序应该是很好理解的,子函数返回的是数组某元素的地址。输出的是这个地址里的值。

#include "stdio.h"

main(){

  int i;

  char *day_name(int n);   

  printf("input Day No:\n");

  scanf("%d",&i);

  if(i<0) exit(1);

  printf("Day No:%2d-->%s\n",i,day_name(i));

}

char *day_name(int n){

  static char *name[]={ "Illegal day",

                        "Monday",

                        "Tuesday",

                        "Wednesday",

                        "Thursday",

                        "Friday",

                        "Saturday",

                        "Sunday" };

  return((n<1||n>7) ? name[0] : name[n]);

}

2、函数指针是指向函数的指针变量,即本质是一个指针变量。

类型说明符 (*函数名)(参数)

int        (*f)  (int x); /* 声明一个函数指针 */

f=func; /* 将func函数的首地址赋给指针f */ 

指向函数的指针包含了函数的地址,可以通过它来调用函数。声明格式如下:
类型说明符 (*函数名)(参数)
其实这里不能称为函数名,应该叫做指针的变量名。这个特殊的指针指向一个返回整型值的函数。指针的声明必须和它指向函数的声明保持一致。
指针名和指针运算符外面的括号改变了默认的运算符优先级。如果没有圆括号,就变成了一个返回整型指针的函数的原型声明。
例如:
void (*fptr)();
把函数的地址赋值给函数指针,可以采用下面两种形式:
fptr=&Function;
fptr=Function;
取地址运算符&不是必需的,因为单单一个函数标识符就标号表示了它的地址,如果是函数调用,还必须包含一个圆括号括起来的参数表。
可以采用如下两种方式来通过指针调用函数:
x=(*fptr)();
x=fptr();
第二种格式看上去和函数调用无异。但是有些程序员倾向于使用第一种格式,因为它明确指出是通过指针而非函数名来调用函数的。下面举一个例子:

#include "stdio.h"

void (*funcp)();

void FileFunc(),EditFunc();

main()

{

funcp=FileFunc;

(*funcp)();

funcp=EditFunc;

(*funcp)();

}

 

void FileFunc()

{

printf("FileFunc\n");

}

 

void EditFunc()

{

printf("EditFunc\n");

}

程序输出为:
FileFunc
EditFunc

例2

#include"stdio.h" 

//定义一个函数指针,形参为一个char类型,一个int类型,返回类型为void 

void (*pf)(char, int); 

void fun(char ,int);  //声明一个函数,形参为一个char类型,一个int类型,返回类型为void 

int main(void) 



      pf=fun;            //给函数指针pf赋值为fun函数的首地址(函数名代表函数的首地址) 

 

  (*pf)('c',372);        //调用pf指向的函数 

  }  

void fun(char a,int b) 



       printf("the argument    is %c and %d\n",a,b); 

}

主要的区别是一个是指针变量,一个是函数。在使用是必要要搞清楚才能正确使用

二、指针的指针
指针的指针看上去有些令人费解。它们的声明有两个星号。例如:
char ** cp;
如果有三个星号,那就是指针的指针的指针,四个星号就是指针的指针的指针的指针,依次类推。当你熟悉了简单的例子以后,就可以应付复杂的情况了。当然,实际程序中,一般也只用到 二级指针,三个星号不常见,更别说四个星号了。
指针的指针需要用到指针的地址。
char c='A';
char *p=&c;
char **cp=&p;
通过指针的指针,不仅可以访问它指向的指针,还可以访问它指向的指针所指向的数据。下面就是几个这样的例子:
char **p1=*cp;
char c1=**p1;
你可能想知道这样的结构有什么用。利用指针的指针可以允许被调用函数修改局部指针变量和处理指针数组。

#include "stdio.h"

void FindCredit(int **);

main()

{

int vals[]={7,6,5,-4,3,2,1,0};

int *fp=vals;

FindCredit(&fp);

printf("%d\n",*fp);

}

void FindCredit(int ** sp)

{

while(**sp!=0)

if(**sp<0) break;

else (*fpp)++;

}
首先用一个数组的地址初始化指针fp,然后把该指针的地址作为实参传递给函数FindCredit()。FindCredit()函数通过表达式**fpp间接地得到数组中的数据。为遍历数组以找到一个负值,FindCredit()函数进行自增运算的对象是调用者的指向数组的指针,而不是它自己的指向调用者指针的指针。语句(*fpp)++就是对形参指针指向的指针进行自增运算的。但是因为*运算符高于++运算符,所以圆括号在这里是必须的,如果没有圆括号,那么++运算符将作用于二重指针fpp上。

三、指向指针数组的指针
指针的指针另一用法旧处理指针数组。有些程序员喜欢用指针数组来代替多维数组,一个常见的用法就是处理字符串。

#include "stdio.h"

char *Names[]={"Bill","Sam","Jim","Paul","Charles","0"};

main()

{

char **nm=Names;

while(**nm!=‘0’)

printf("%s\n",*nm++);

}

先用字符型指针数组Names的地址来初始化指针nm。每次printf()的调用都首先传递指针nm指向的字符型指针,然后对nm进行自增运算使其指向数组的下一个元素(还是指针)。注意完成上述认为的语法为*nm++,它首先取得指针指向的内容,然后使指针自增。
  深圳广州南宁长沙郑州嵌入式单片机C语言技术提升联系郭老师qq754634522,年底优惠多多,添加咨询可免费领取学习优惠券哦

注意数组中的最后一个元素被初始化为0,while循环以次来判断是否到了数组末尾。具有零值的指针常常被用做循环数组的终止符。程序员称零值指针为空指针(NULL)。采用空指针作为终止符,在数组增删元素时,就不必改动数组的代码,因为此时数组仍然以空指针作为结束。

#include "stdio.h"

main()

{

char *name[]=

{"Follow me","BASIC","Great Wall","FORTRAN","Computer desighn"};

char **p;

int i;

for(i=0;i<5;i++)

{

  p=name+i;

  printf("%s\n",*p);

 }

}

/* typedef与define之间的区别*/

#include "stdio.h"

#define PIN1 int * 

typedef int * PIN2;

void main()

 {

  PIN1 a=1,b=1;

  PIN2 c=3,d=3;

  printf("%d",a);  //a是 指针  1

  printf("\n");

  printf("%d",a+1); //a地址加1,由于是整型占4个字节  5

  printf("\n");

  printf("%d",b);  //b是 整型 值  1

  printf("\n");

  printf("%d",b+1); //b的值自增1   2

  printf("\n");

  printf("%d",c);   //c是 指针   1

  printf("\n");

  printf("%d",c+1);  //c地址加1,由于是整型占4个字节  5

  printf("\n");

  printf("%d",d);   //d是 指针   1

  printf("\n");

  printf("%d",d+1);  //d地址加1,由于是整型占4个字节  5

  }
信盈达科技有限公司专业提供嵌入式、ARM、LINUX、Android、FPGA、PCB、单片机等高端软硬件技术方案设计和培训,公司具有雄厚的研发实力,多个分点,免费试听,包就业。欢迎咨询郭老师13641462598 QQ754634522
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

14

主题

338

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
464
金钱
464
注册时间
2013-6-15
在线时间
15 小时
发表于 2014-12-5 20:47:11 | 显示全部楼层
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
22
金钱
22
注册时间
2014-12-8
在线时间
0 小时
发表于 2014-12-8 21:26:52 | 显示全部楼层
你这帖子发的,标题不好。还以为是请教别人呢。原来是经验帖。楼主改下 会有更多人支持。
回复 支持 反对

使用道具 举报

70

主题

119

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
433
金钱
433
注册时间
2013-8-19
在线时间
2 小时
 楼主| 发表于 2014-12-10 11:29:28 | 显示全部楼层
嗯嗯嗯,谢谢支持
信盈达科技有限公司专业提供嵌入式、ARM、LINUX、Android、FPGA、PCB、单片机等高端软硬件技术方案设计和培训,公司具有雄厚的研发实力,多个分点,免费试听,包就业。欢迎咨询郭老师13641462598 QQ754634522
回复 支持 反对

使用道具 举报

1

主题

12

帖子

0

精华

新手上路

积分
39
金钱
39
注册时间
2014-7-20
在线时间
2 小时
发表于 2014-12-19 22:58:26 | 显示全部楼层
顶顶顶顶顶!!!!!支持
IT菜鸟逆袭记~~~~
回复 支持 反对

使用道具 举报

16

主题

189

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1296
金钱
1296
注册时间
2013-8-27
在线时间
503 小时
发表于 2014-12-27 15:21:10 | 显示全部楼层
顶!!!!!!!!!
回复 支持 反对

使用道具 举报

70

主题

119

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
433
金钱
433
注册时间
2013-8-19
在线时间
2 小时
 楼主| 发表于 2015-1-13 14:59:56 | 显示全部楼层
谢谢大家的支持,想系统学习C语言单片机嵌入式的朋友可联系郭老师qq754634522
信盈达科技有限公司专业提供嵌入式、ARM、LINUX、Android、FPGA、PCB、单片机等高端软硬件技术方案设计和培训,公司具有雄厚的研发实力,多个分点,免费试听,包就业。欢迎咨询郭老师13641462598 QQ754634522
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 12:49

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表