《彻底搞定C指针》文档整理

一.变量存储

#include <stdio.h>
 int main(void)
 {
     int i = 39;
     printf(“%d\n”, i); 
     printf(“%d\n”, &i); //十进制打印i的地址
     printf(“%x\n”, &i); //十六进制打印i的地址 
     return(0);
}
/*得到结果:
ray@ray-Lenovo:~/Documents/Exec_important/Daily$ ./0128-2
39
23300652
1638a2c
ray@ray-Lenovo:~/Documents/Exec_important/Daily$ ./0128-2
39
1367552540
5183321c
ray@ray-Lenovo:~/Documents/Exec_important/Daily$ ./0128-2
39
1684339276
6464fa4c
每次得到的地址都不同*/

二. 什么是指针

#include <stdio.h>
int main(void)
{
    char a, *pa;
    a = 10;
    pa = &a; /* pa指向变量a的地址 */
    *pa = 20; /* 给变量a的地址的内容赋值为20, 即a=20*/
    printf("%d\n", a);
}
/* 得到结果: 20 */

三. 指针与数组名

#include <stdio.h>
int main(void)
{
    int i, *pa, a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    //int * const pa = a; //不行, pa被定义为常量指针了
    pa = a;

    printf("array mode:\n");
    for(i = 0; i < 10; i++)
        printf("%d ", a[i]);
    printf("\npointer mode:\n");
    for(i = 0; i < 10; i++)
        printf("%d ", *(a+i));
    printf("\n\n");
    for(i = 0; i < 10; i++)
        printf("%d ", pa[i]);
    printf("\n");
    for(i = 0; i < 10; i++)
        printf("%d ", *(pa+i));
    printf("\n");
    for(i = 0; i < 10; i++)
    {    
        printf("%d ", *pa);
        pa++;
    }    
    printf("\n");
    return 0;
}
/*执行后显示:
array mode:
0 1 2 3 4 5 6 7 8 9 
pointer mode:
0 1 2 3 4 5 6 7 8 9 

0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9   
*/

四. const int pi与int const pi的区别

#include <stdio.h>
int main(void)
{    
    int i1 = 30, i2 = 40;
    const int *pi = &i1;
    pi = &i2; /* 注意这里, pi 可以在任意时候重新赋值一个新内存地址*/
    i2 = 80; /* 这里能用*pi = 80 来代替吗?当然不能! */ 
    printf("%d\n", *pi); /* 输出是 80 */
    return 0;
}
/*pi 的值是可以被修改的。即它可以重新指向另一个地址的,但是,不能通过*pi 来修改 i2 的值*/
#include <stdio.h>
int main(void)
{    
    int i1 = 30, i2 = 40;
    int *const pi = &i1;
    /* pi = &i2; 注意这里, pi 不能再这样重新赋值了,即不能再指向另一个新地址 */
    i1 = 80; /* 这里能用 *pi = 80; 来代替吗?可以,这里可以通过*pi 修改 i1 的 */ 
    printf("%d\n", *pi); /* 输出是 80 */
    return 0;
}
/*pi 的值是可以被修改的。即它可以重新指向另一个地址的,但是,不能通过*pi 来修改 i2 的值*/

总结:

1) 如果 const 修饰在pi 前,则不能改的是pi(即不能类似这样: *pi=50;赋值)而不是指 pi。

2) 如果 const 是直接写在 pi 前,则 pi 不能改(即不能类似这样:pi=&i; 赋值)。

五. 函数参数的传递

Q1. 值传递

#include <stdio.h>
void Exchg1(int x, int y)
{
    int tmp;
    tmp = x;
    x = y;
    y = tmp;
    printf("x = %d, y = %d\n", x, y);
}

int main(void)
{
    int a = 4, b = 6;
    Exchg1(a, b);
    printf("a = %d, b = %d\n", a, b);    
    return 0;
}
/*编译执行,输出:
x = 6, y = 4
a = 4, b = 6
*/

Q2. 地址传递

#include <stdio.h>
void Exchg2(int *px, int *py)
{
    int tmp = *px;
    *px = *py;
    *py = tmp;
    printf("*px = %d, *py = %d\n", *px, *py);
}

int main(void)
{
    int a = 4, b = 6;
    Exchg2(&a, &b);
    printf("a = %d, b = %d.\n", a, b);    
    return 0;
}
/*编译执行,输出:
*px = 6, *py = 4
a = 6, b = 4
*/

Q3. 引用传递

#include <stdio.h>
void Exchg3(int &x, int &y) /* 注意定义处的形式参数的格式与
值传递不同 */
{
    int tmp = x;
    x = y;
    y = tmp;
    printf("x = %d, y = %d.\n", x, y);
}

main()
{
    int a = 4;
    int b = 6;
    Exchg3(a, b); /*注意:这里调用方式与值传递一样*/
    printf("a = %d, b = %d.\n", a, b);
}
/*编译报错,因为C没有引用的用法,C++才*/

六. 指向另一指针的指针

#include <stdio.h>
void find1(char array[], char search, char **ppa)
{
    int i;
    for(i = 0; *(array + i) != 0; i++)
    {
        if(*(array + i) == search)
        {
            *ppa = array + i;
            break;
        }
        else if(*(array + i) == 0)
        {
            *ppa = 0;
            break;
        }
    }
}

int main(void)
{
    char str[] = {"afsdfsdfdf\0"};
    char a = 'd';
    char *p = 0;
    find1(str, a, &p);
    if(0 == p)
        printf("没找到!\n");
    else
        printf("找到了,p = %x\n", p);
    return 0;
}
/*编译执行,输出:
找到了,p = 6393eb53
*/

七. 函数名与函数指针

1.

#include <stdio.h>
void MyFun(int x); //也可写成void MyFun(int)
void (*FunP)(int); //也可写成void (*FunP)(int x)
int main(int argc, char* argv[])
{
    MyFun(10);
    FunP = &MyFun;
    (*FunP)(20);
}

void MyFun(int x)
{
    printf("%d\n", x);
}
/*编译执行,输出:
10
20
*/

2.

#include <stdio.h>
void MyFun(int x); //也可写成void MyFun(int)
void (*FunP)(int); //也可写成void (*FunP)(int x)
int main(int argc, char* argv[])
{
    MyFun(10);
    FunP = MyFun;
    FunP(20);
    return 0;
}

void MyFun(int x)
{
    printf("%d\n", x);
}
/*编译执行,输出:
10
20
*/

3.

#include <stdio.h>
void MyFun(int x); //也可写成void MyFun(int)
void (*FunP)(int); //也可写成void (*FunP)(int x)
int main(int argc, char* argv[])
{
    MyFun(10);
    FunP = &MyFun;
    FunP(20);
}

void MyFun(int x)
{
    printf("%d\n", x);
}
/*编译执行,输出:
10
20*/

4.

#include <stdio.h>
void MyFun(int x); //也可写成void MyFun(int)
void (*FunP)(int); //也可写成void (*FunP)(int x)
int main(int argc, char* argv[])
{
    MyFun(10);
    FunP = MyFun;
    (*FunP)(20);
}

void MyFun(int x)
{
    printf("%d\n", x);
}
/*编译执行,输出
10
20
*/

5.

#include <stdio.h>
void MyFun(int x); //也可写成void MyFun(int)
void (*FunP)(int); //也可写成void (*FunP)(int x)
int main(int argc, char* argv[])
{
    (*MyFun)(10);
    FunP = &MyFun;
    (*FunP)(20);
}

void MyFun(int x)
{
    printf("%d\n", x);
}
/*编译执行,输出:
10
20
*/

总结上面:1)其实, MyFun 的函数名与 FunP 函数指针都是一样的, 即都是函数指针。 MyFun 函数名是一个函数指针常量,而 FunP 是一个函数数指针变量,这是它们的关系。

2)但函数名调用如果都得如(*MyFun)(10)这样,那书写与读起来都是不方便和不习惯的。所以 C 语言的设计者们才会设计成又可允许 MyFun(10)这种形式地调用(这样方便多了并与数学中的函数形式一样,不是吗?)。

3)为统一起见, FunP 函数指针变量也可以 FunP(10)的形式来调用。

4)赋值时,即可 FunP = &MyFun 形式,也可 FunP = MyFun。

6.

#include <stdio.h>
void MyFun(int x); //也可写成void MyFun(int)
typedef void (*FunType)(int);
FunType FunP;
int main(int argc, char* argv[])
{
    //FuncType FunP;/*函数指针变量也可以是局部的*/
    MyFun(10);
    FunP = &MyFun;
    FunP(20);
    return 0;
}

void MyFun(int x)
{
    printf("%d\n", x);
}
/*编译执行,输出:
10
20
*/

7.

#include <stdio.h>
void MyFun1(int x);
void MyFun2(int x);
void MyFun3(int x);
typedef void (*FunType)(int);
void CallMyFun(FunType fp, int x);
int main(int argc, char* argv[])
{
    CallMyFun(MyFun1, 10);    
    CallMyFun(MyFun2, 20);
    CallMyFun(MyFun3, 30);
}

void CallMyFun(FunType fp, int x)
{
    fp(x);
}

void MyFun1(int x)
{
    printf("函数MyFun1中输出:%d\n", x);
}

void MyFun2(int x)
{
    printf("函数MyFun2中输出:%d\n", x);
}

void MyFun3(int x)
{
    printf("函数MyFun3中输出:%d\n", x);
}
/*
函数MyFun1中输出:10
函数MyFun2中输出:20
函数MyFun3中输出:30
*/

原文链接: https://www.cnblogs.com/try-again/p/5166561.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/228151

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月13日 下午1:51
下一篇 2023年2月13日 下午1:51

相关推荐