C语言中*和&的一些用法及难点

这篇具有很好参考价值的文章主要介绍了C语言中*和&的一些用法及难点。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在学习数据结构期间,我们总会由于伪代码和C与C++的混淆理解导致无法正确使用*和&,其实通过简单的总结和实验对*和&的作用进行整理可以加深理解。

&的作用比较好理解,取地址符,即通过“&变量名”可以获取该变量的地址,也就是指针,可以将结果赋给同类型的指针变量。
而*可以用在两个地方,一是“数据类型关键字 *变量名”的形式,可以定义一个指向该数据类型的指针;二是“*指针变量”的形式,可以根据该指针变量取出其指向的数据。下面通过一些实例和应用场景来进一步分析。

定义指针

  • 方式一:可以使用typedef的方式定义一个可以定义指针变量的关键字
  • 方式二:可以使用“基本数据类型关键字 *变量名”的方式定义指针
typedef int *pInt;  //方式一
    int a=1;
    pInt p1=&a;
    int *p2=&a;     //方式二

    scanf("%d",&a);
    printf("%d",a);
    
    scanf("%d",p1);
    printf("%d",a);
    
    scanf("%d",p2);
    printf("%d",a);

通过程序运行结果可以发现,p1和p2都是指向变量a的整型指针变量。

定义函数

这里牵涉到另一个容易混淆的地方——形参与实参,按照字面意思来讲,形参就是形式参数,并非实际变量,类似于生活中的“规范”,通过规范的束缚使函数调用者必须要传入对应类型的数据方能通过解析;而实参就是有实际数据的参数,通过了“规范”的校验后才能被函数加工处理。
指针变量也可以作为参数传入函数,其目的并不是要修改指针变量,而是要达到通过指针在函数内部操作函数外部数据的目的,以解决函数作用域的问题。

#include <stdio.h>
void update(int *p,int x){ 	//函数要求传入一个整型指针和一个整型参数
    *p = 9;	//通过指针修改参数的值
    x = 10; //直接修改参数的值
};
int main(){
 	int a = 2;
    int b = 4;
    update(&b,a);
    printf("a=%d,b=%d",a,b);
    return 0;
}

运行结果为a=2,b=9,可见函数通过指针可以修改b的值,而不可以通过参数修改a的值。

定义数组

在c语言中定义数组可以用int arr[2]={1,2};的形式,其本质也是一个指针。

int arr[3]={1,2,3};
int *p=arr;
printf("%d",p[0]);

通过上例可以看出数组名本身就是一种整型指针类型,故当数组做函数参数时还可以这样实现:

#include <stdio.h>
void test(int *arr){
    arr[0]=10;
}
int main(){
    int arr[3]={1,2,3};
    test(arr);
    printf("%d",arr[0]);
}

关于结构体数据的访问

在定义的函数中操作结构体时,有两种方式,一种是使用结构体的指针直接访问数据,一种是使用结构体变量名访问。
在实例中可见,使用指针访问结构体数据时是以“指针->数据”的形式,使用变量名可以使用“变量名.数据”的形式。明显可以看出,下例中(*pL)等同于L,使用“.”的方式访问数据。

#include "stdio.h"

typedef struct{
    int data[3];
}list,*pList;

int main(){    
    list L;
    pList pL = &L;
    pL->data[0]=2;
    L.data[1]=3;
    (*pL).data[2]=4;
    printf("data[0]=%d,data[1]=%d,data[2]=%d",L.data[0],L.data[1],L.data[2]);
    //data[0]=2,data[1]=3,data[2]=4
}

关于使用函数修改指针

在学习链表时,我们会接触到修改头指针的问题,定义函数修改指针的指向,如果我们要在函数中修改指针,就要将传入的参数设定为指针的指针,具体代码:

#include <stdio.h>

void InitList1(int *a,int *b){
    a=b;
}
void InitList2(int **a,int **b){
    *a=*b;
}

int main(){
    int *c;
    int *d;

    printf("c=%p,d=%p\n",c,d);    // c=0000000000000010,d=0000000000A614E0
    InitList1(c,d);
    printf("c=%p,d=%p\n",c,d);    // c=0000000000000010,d=0000000000A614E0
    InitList2(&c,&d);
    printf("c=%p,d=%p\n",c,d);    // c=0000000000A614E0,d=0000000000A614E0

}

可以看出,如果直接将指针传入函数进行修改是不会生效的,此外还有另一种写法:

#include <stdio.h>

void InitList1(int *a,int *b){
    a=b;
}
typedef int *Elem;
void InitList2(Elem &a,Elem &b){
    a=b;
}

int main(){
    int *c;
    int *d;

    printf("c=%p,d=%p\n",c,d);    // c=0000000000000010,d=00000000001B14E0
    InitList1(c,d);
    printf("c=%p,d=%p\n",c,d);    // c=0000000000000010,d=00000000001B14E0
    InitList2(c,d);
    printf("c=%p,d=%p\n",c,d);    // c=00000000001B14E0,d=00000000001B14E0

}

若当前源程序文件后缀为.c,则这种写法在编译器中会报错,但是执行结果正确,因为这是c++的语法,而开发工具使用的是c的语法检查标准,若将源程序文件后缀改为.cpp,则编译器不会提示语法报错,而且仍然可以正确运行。

小结

通过以上实例可以感受到,指针结合数组和函数等应用,可以更加灵活的设计程序,加深对程序运行中数据传输原理的理解。文章来源地址https://www.toymoban.com/news/detail-737889.html

到了这里,关于C语言中*和&的一些用法及难点的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • web架构师编辑器内容-数据结构设计上面的难点

    组件的属性应该怎样设计 业务组件分为:样式属性和其他属性,样式属性就是css,其他属性拿文本来说,就是比如test还有点击事件等。 有两种方案: 方案一:把css作为统一的对象传入: 方案二:将所有的属性全部平铺传入 这两种方案,第二种方案相比于第一种比较好,第

    2024年01月22日
    浏览(56)
  • 【数据结构】链表C语言编写的,它定义了一个链表,并实现了一些基本的链表操作,如创建新节点、插入节点、清空链表、输出链表以及查找节点

    这段代码是用C语言编写的,它定义了一个链表,并实现了一些基本的链表操作,如创建新节点、插入节点、清空链表、输出链表以及查找节点。以下是每段代码的详细解释: 文件注释: 这段代码是一个文件注释 包含头文件: #include stdio.h  和  #include stdlib.h :这两个头文件

    2024年02月09日
    浏览(46)
  • InnoDB底层的一些主要数据结构

    MySQL的InnoDB存储引擎使用了一些关键的底层数据结构来优化数据的存储、索引和查询。以下是InnoDB底层的一些主要数据结构: 1. **B+树索引**:    - InnoDB的主要数据结构是B+树(平衡树的一种变体),用于存储表数据和索引。    - 每个InnoDB表都有一个主键索引(如果没有显式

    2024年02月01日
    浏览(44)
  • Go数据结构----你必须知道的一些

    算法(英文 algorithm )这个词在中文里面博大精深,表示算账的方法,也可以表示运筹帷幄的计谋等。在计算机科技里,它表示什么呢? 计算机,顾名思义是用来计算的机器。算法在计算机科学中可以描述为:计算机接收一个输入指令,然后进行一个过程处理,最后输出计算

    2024年02月03日
    浏览(46)
  • 2022BUAA数据结构期末大作业的一些想法

            本文写的内容可能在很多巨佬看来属实是一些简单的废话,但我的底子比较薄,很多东西都是想了好久,这篇文章的主要目的实际上也只不过是把我的一些改进的地方记录下来,防止以后忘记。。。 百度、谷歌等互联网搜索引擎提供高效的网页、文档搜索功能,

    2024年02月10日
    浏览(57)
  • 【数据结构】队列实现+层序遍历详解+一些练题

    欢迎来到我的: 世界 希望作者的文章对你有所帮助,有不足的地方还请指正,大家一起学习交流 ! 国庆到了,也要内卷一下,感谢所以老铁们的支持!😎 1、队列的定义 队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。 队列是一种先进先出(

    2024年02月08日
    浏览(39)
  • 数据结构中一些零碎且易忘的知识点

    第一章 绪论 数据结构包含三个方面的内容: 数据的逻辑结构:描述数据之间逻辑关系的、与数据的存储无关的数学模型。相同的逻辑结构可使用不同的存储结构存储,如线性表既可顺序存储,也可链式存储 线性结构:一个线性表是n个具有相同特性的数据元素的有限序列 一

    2024年02月14日
    浏览(41)
  • Java 中数据结构LinkedList的用法

    链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。 链表可分为单向链表和双向链表。 一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接。 一个双向链表有三个整

    2024年02月11日
    浏览(41)
  • Java 中数据结构HashSet的用法

    HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。 HashSet 允许有 null 值。 HashSet 是无序的,即不会记录插入的顺序。 HashSet 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是不确定的。 您必须在多线程访问时显式同步对 HashSet 的并发访问。 Ha

    2024年02月11日
    浏览(44)
  • Java 中数据结构ArrayList的用法

    ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。 ArrayList 继承了 AbstractList ,并实现了 List 接口。 add() 将元素插入到指定位置的 arraylist 中 addAll() 添加集合中的所有元素到 arraylist 中 clear() 删除 arraylist 中的所

    2024年02月10日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包