指针_C语言

作者: MathCat | 来源:发表于2016-09-11 21:26 被阅读0次

基础

  • 内存:是通过连续的内存编号来管理的(内存的地址)
  • 指针:指针变量里边存储的就是内存地址

值和类型

不能简单通过检查一个值的位来判断它的类型,值得类型取决于其使用方式

未初始化和非法指针

int *a;
*a = 12;

访问未初始化的指针是非法的

指向指针的指针

int a = 12;
int *b = &a;
int **c = &b;
*操作符具有从右向左的结核性,所以这个表达式相当于*(*c)

定义

*a 间接访问

通过一个指针访问它所指向的地址的过程称为间接访问(indirection)或解引用指针(dereferencing the pointer),这个用于执行间接访问的操作符是单目操作符*

int a = 10;
int *p = &a;
  • int *p表示:表达式*p产生的结果类型是int类型
  • int *并不是一个类型,原因如下
int* b,c,d;

这并不是将三个变量声明为指向整型的指针,b是一个指针,其余两个变量为普通整型

&b 取地址符

int *pb = &b;// & scanf函数中有一个取地址符指针变量可以通过地址赋值

%p 指针占位符

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

NULL指针

对一个NULL指针进行解引用操作是非法的

NULL类似于给普通变量赋初始值的0,其实就是地址为0

int *p =NULL;//定义了一个指针变量,初始值为NULL
float*p1 = NULL;//浮点型指针
double *p2 =NULL;
char *p3 =NULL;

指针的算术运算

int *pp =NULL;
int num1 = 10;

pp = &num1;

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

指针的算术运算需要根据指针类型去计算,指针+ 1是向高位移动一个类型所占的字节数,指针- 1是向低位移动一个类型所占的字节数

printf("%p\n",pp++);
printf("%p\n",++pp);
printf("%p\n",pp);

++ --还是遵循之前++ --运算符法则

指针的重指向

咱们可以让指针重新指向另一个变量(内存的另一块区域),这就叫指针的重指向
我们可以通过指针修改内存地址上的值

int number1 = 10;
int *pNum1 = &number1;

int number2 = 8;
pNum1 = &number2;

*pNum1 = 9;
printf("%d\n",*pNum1);
printf("%d\n",number2);

用指针交换两个数的值

  • 函数在传参数的时候,形式参数只是拷贝了实际参数的内容或者值,实际参数并未发生改变
  • 有了指针我们可以直接操作指针指向的内存区域,然后修改内存中的值
int num1 = 12;
int num2 = 16;
swapTwoNumbers(&num1, &num2);
printf("%d %d\n",num1,num2);

指针与数组的关系

数组名就是数组的地址,它恒等于数组元素的首地址

实际上*(arr1 + i) = arr[i];

int arr1[4] = {1,2,3,4};
for(inti = 0; i < 4; i++) {
    printf("%p\n",arr1+0);
}

printf("%lu\n",sizeof(arr1));//数组名虽然是地址,但是我们利用它计算内存空间的话,还是根据里边存储的数据类型而定

int *pp = &num1;

printf("%lu\n",sizeof(pp));//打印一个单纯的变量地址的话,并不是根据类型而定

printf("%lu\n",sizeof(&num1));

char aa = 'w';
char *pp1 = &aa;

printf("%lu\n",sizeof(pp1));//指针类型所占的字节数与计算机本身的计算位数有关,如果是32位的计算机,指针类型占4个字节,如果是64位的计算机,指针类型占8个字节
   
short array[4] = {1,2,3,4};

int *p = array;//不匹配的指针类型

数组名确实能够打印出数组元素的首地址,但是如果把数组名认为就是地址是不准确的,实际上数组名是一个常量

指针与字符串的关系

char name[] ="guozhenyan";
char *p1 = name;

printf("%p\n",p1);

for(int i = 0; i <strlen(name); i++) {
    printf("%c\n",*(p1+i));
}

指针数组

char *a[10] = {"ddd","sdq","das","qwe","cva","btg","aaa","ccc","eee","fff"};

printf("%p\n",a);//数组指针的地址
printf("%p\n",a+1);//对数组指针地址进行操作
printf("%p\n",a[0]);//对存的数据地址进行操作
printf("%p\n",a[1]);

printf("%p\n",*a);//存的是地址
printf("%p\n",*(a+1));

printf("%c\n",**a);
printf("%c\n",**(a+1));

printf("%c\n",*a[0]);
printf("%c\n",*a[1]);

结构体指针

typedef struct person {
   char name[20];
   int age;
   int score;
}Person;

Person p1 = {"guangguang",16,90};
Person p2 = {"jintao",18,99};
Person p3 = {"wangce",17,88};
      
void printArr(Person*p,intcount){
for(int i = 0; i < count; i++) {
printf("%s,%d,%d\n",(*(p+i)).name,(p+i)->age,(*(p+i)).score);
}
    //使用指针去访问结构体数组的成员变量的时候,可以使用-> 
Person arr[3] = {p1,p2,p3};

函数指针

函数名跟数组名类似,实际上它也是一个地址

printf("%p\n",helloWorld);

我们也可以找一个指针,指向函数名所在的地址.这个指针就是所谓的函数指针

函数的指针类型根据函数的返回值和参数而定
返回值类型+ (*指针名) +参数的类型=函数指针

void (*p1)() =NULL;
p1 =helloWorld;//声明
p1();//调用方式
void (*p2)(int) =NULL;

p2 =printNumber;
p2(31415);

BOOL (*p3)() =backYes;

printf("%d\n",p3());

int (*p4)(int,int) =sum;
printf("%d\n",p4(8,4));

函数指针可以重新指向别的函数,只要函数类型一样就可以重指向

char a[10];

printf("请输入函数名:\n");

scanf("%s",a);

int(*p5)(int,int) =NULL;

printf("请输入a,b的值:\n");

int b,c;
scanf("%d%d",&b,&c);

if(strcmp(a,"maxValue") == 0){
p5 =max;
}else if(strcmp(a,"sum") == 0){
p5 =sum;
}else{
printf("输入有误\n");
return 0;
}
//现在p5这个指针并没有指向认可地址,也可以导致程序崩溃,这种情况叫作野指针

printf("%d\n",p5(b,c));

替换指针类型

typedef int (*pGet)(int,int);//重新定义函数指针的类型:pGet
//我们利用typedef这个关键字还可以重新定义函数指针的类型变成一个新的类型*后边跟上我们新类型的名字

函数指针的作用

  1. ️函数指针是OC中block的底层实现,OC中block得形式跟函数指针一模一样.
  2. ️函数指针因为可以重指向不同函数,可以起到简化代码和解耦合的作用

函数回调(用函数指针作为函数参数)

int(*p)(int,int) =NULL;
p = max;//函数指针指向的函数可能实现的功能比较复杂,或者是公司核心代码,我们一般程序员不需要知道里面的详细内容,只需要会调用即可.(面向对象语言,封装特性的底层(雏形))

函数转移表

//常规写法
switch ( oper ){
    case ADD:
        result = add( oper1, oper2 );
        break;
    case SUB:
        result = sub( oper1, oper2 );
        break;
    case MUL:
        result = mul( oper1, oper2 );
        break;
    case DIV:
        result = div( oper1, oper2 );
        break;
    ...
}
//使用转移表之后的写法
double add( double, double );
double sub( double, double );
double mul( double, double );
double div( double, double );
...
double (*oper_func[])( double, double ) = {
    add, sub, mul, div, ...
};
//下面的语句替换前面整条switch语句
result = oper_func[ oper ]( op1, op2 );

范指针

void *p;
memcpy;

类型转换

fptr = (float *) iptr;

相关文章

  • C语言05- 指针

    C语言05- 指针 13:指针 指针是C语言中的精华,也是C语言程序的重点和难点。 13.1:指针定义与使用 指针...

  • 02-C语言的指针

    02-C语言的指针 目标 C语言指针释义 指针用法 指针与数组 指针与函数的参数 二级指针 函数指针 指针在C中很...

  • C语言指针总结大学霸IT达人

    C语言指针总结大学霸IT达人 C语言的指针是C语言区别其它语言的最主要的特定之一。有了指针,C语言就可以抛开所有束...

  • 带小白学C语言指针

    C语言里指针才是C语言的开始和指针;C语言里基本所有东西都是由指针演变而成; 指针是指向地址的变量,类型就是指针...

  • 在Swift中使用C语言的指针

    在Swift中使用C语言的指针 在Swift中使用C语言的指针

  • [Swift]结构体指针操作

    C语言的指针操作 在c语言中申明一个变量并通过指针修改该变量的值 a value is 2 c语言操作结构体指针操...

  • Go语言-指针

    Go语言中的指针不同于C语言,Go语言的指针使用方法要简单很多。当然和C语言从指针定义到指针的使用都有很大的不同。...

  • C语言中的指针与数组

    C语言中的指针与数组 @(C语言)[排序算法, 快速排序, C实现] 引言 相信指针与数组是不少同学在初学C语言时...

  • 指针数组和数组指针

    指针数组|存储指针的数组 在C语言和C++语言中,数组元素全为指针的数组称为指针数组。 例如:int *p[10]...

  • iOS开发 -- C语言基础8(指针)

    iOS开发 -- C语言基础8(指针) 指针是C语言中非常重要的数据类型,如果你说C语言中除了指针,其他你都学得很...

网友评论

    本文标题:指针_C语言

    本文链接:https://www.haomeiwen.com/subject/kqauettx.html