学习C指针

指针基本介绍

计算机中的每个内存都有地址

整型分配4字节,字符分配1字节 ,浮点数分配4字节

指针是一个变量,它存放着另外一个变量的地址

int a;
int *p;
p = &a;//
a = 5;
printf(p)  //get a address
print &a   //get a address
print &p   //get p address
print *p   //得到指针所指向的地址的值

p = address

*p = value at address

 当指针变量前面没有加*号进行操作,是在对地址进行操作,

*p则是对指针所指向的地址操作

指针代码示例

#include<stdio.h>
#include<stdlib.h>
int main()
{
    int a = 10;
    int *p = &a;
    //p = &a;//&a = address of a
    //int* p 意外着指向整型的指针然后写出变量名
    printf("Address of p is %d\n",p);
    printf("Value at p is %d\n",*p);


    printf("%d\n",p);
    printf("%d\n",*p);//*p = value at address pointed by p
    printf("%d\n",&a);
    printf("a = %d\n",a);


    *p = 12;//使用指针对所指向的地址值进行修改
    printf("a = %d\n",a);

    int b = 20;
    *p = b;
    printf("Address of p is %d\n",p);
    printf("Value at p is %d\n",*p);

    system("pause");
    return 0;
}
#include <stdio.h>
#include <stdlib.h>

int main() {
    int a = 10;
    int *p;
    p = &a;
    //Pointer arithmetic
    printf("Address p is %d\n",p);
    printf("value at address p is %d\n",*p);
    printf("size of integer is %d bytes\n",sizeof(int));
    printf("Address p+1 is %d\n",p+1); //增加4字节以得到下一个整型的地址

    system("pause");
    return 0;
}

 指针的类型,算术运算,void指针

指针是强类型

我们需要一个特定类型的指针变量来存放特定类型变量的地址 

byte3byte2byte1byte0
00000000000000000000010000000001
203202201200
最左边为符号位2的10次方2的一次

剩下的31个位用来存储值

#include <stdio.h>
#include <stdlib.h>

int main() {
    int a = 1025;
    int *p;
    p = &a;
    //Pointer arithmetic
    printf("size of integer is %d bytes\n",sizeof(int));
    printf("Address = %d,value = %d\n",p,*p);

    char *po;
    po = (char*)p;
    printf("size of char is %d bytes\n",sizeof(char));
    printf("Address = %d,value = %d\n",po,*po);
    printf("Address = %d,value = %d\n",po+1,*(po+1));

    system("pause");
    return 0;
}

 通用指针类型,不针对某个特定的数据类型,这种指针类型被称为void类型的指针

void *p

指向指针的指针(pointer to pointer)

#include <stdio.h>
#include <stdlib.h>

int main() {
    int x = 5;
    int *p = &x;
    *p = 6;
    int **q = &p;
    int ***r = &q;
    
    printf("%d\n",*p);//指针p所指向的内存地址的值
    printf("%d\n",*q);//指针q所指向的指针p的地址
    printf("%d\n",*(*q));//指针q所指向的指针q的地址,指针p所指向的地址值
    printf("%d\n",*(*r));
    printf("%d\n",*(*(*r)));

    //变量x是整型,为了得到x的地址,需要int* 类型的指针
    //为了存储p地址,需要一个指向int*类型的指针,为此再加一个*,表示这个指针指向的是int*
    //可以无限套娃

    system("pause");
    return 0;
}

函数传值vs传引用

当我们在函数里面声明一个变量,我们把它叫做局部变量,我们只能在声明了变量的地方使用这个变量

#include<stdio.h>
#include<stdlib.h>

void Increment(int a)
{
    a = a + 1;
    printf("Address of variable a in increment = %d\n",&a);
}

int main()
{
    int a;
    a = 10;
    Increment(a);
    printf("Address of variable a in main = %d\n",&a);

    system("pause");
    return 0;
}

main函数的a与自增函数的a的地址不一样

应用程序所使用的内存如下表格 

内存
Heap
Stack
Static/Global
Code(Text)

第一部分(Code):用来存储程序的指令,计算机需要把指令加载到内存,就像上面程序中的自增语句

第二部分:分配给静态或者全局变量

如果我们不是在函数中声明变量,那么它将会是一个全局变量(Global),作为一个全局变量,在程序的任何地方都可以访问和修改。

局部变量只能在特定的函数或者特定的代码块进行访问和修改。

第三部分:局部变量都放在stack部分

第四部分:堆

内存中的四个部分,一二三是固定的,应用程序在运行时可以要求在堆区为它分配跟多的内存

当我们在主函数中调用其它函数,这个参数被称为实参,被调函数中的参数被称为形参,调用时,实参被映射到形参

传引用

#include<stdio.h>
#include<stdlib.h>

void Increment(int *p)
{
    *p = (*p) + 1;
}

int main()
{
    int a;
    a = 10;
    Increment(&a);
    printf("a = %d\n",a);

    system("pause");
    return 0;
}

指针和数组

#include<stdio.h>
#include<stdlib.h>

int main()
{
    int A[] = {2,4,5,8,1};
    printf("%d\n",A);
    printf("%d\n",&A[0]);
    printf("%d\n",A[0]);
    printf("%d\n",*A);

    system("pause");
    return 0;
}
#include<stdio.h>
#include<stdlib.h>

int main()
{
    int A[] = {2,4,5,8,1};
    int i;
    for(i = 0;i < 5;i++)
    {
        printf("Address = %d\n",&A[i]);
        printf("Address = %d\n",A+i);
        printf("Value = %d\n",A[i]);
        printf("value = %d\n",*(A+i));
    }

    system("pause");
    return 0;
}

数组作为函数参数

#include<stdio.h>
#include<stdlib.h>

int SumOfElements(int A[],int size)
{
    int i,sum = 0;
    for(i = 0;i < size;i++)
    {
        sum+= A[i];
    }
    return sum; 
}

int main()
{
    int A[] = {1,2,3,4,5};
    
    int size = sizeof(A)/sizeof(A[0]);
    //用数组A的大小除以A[0]的大小,这样就会得到数组中元素的个数
    int total = SumOfElements(A,size);
    printf("Sum of elements = %d\n",total);

    system("pause");
    return 0;
}
#include<stdio.h>
#include<stdlib.h>

int SumOfElements(int A[])//A是一个整型指针,而在main函数中A是一个数组
{
    int i,sum = 0;
    int size = sizeof(A)/sizeof(A[0]);
    printf("SOE - Size of A = %d,size of A[0] = %d\n",sizeof(A),sizeof(A[0]));
    //'sizeof' on array function parameter 'A' will return size of 'int*' 
    //当编译器看到数组作为函数参数的时候,它不会拷贝整个数组,这里我们不是拷贝变量的值,而仅仅是拷贝变量的地址
    for(i = 0;i < size;i++)
    {
        sum+= A[i];
    }
    return sum; 
}

int main()
{
    int A[] = {1,2,3,4,5};
    
    
    //用数组A的大小除以A[0]的大小,这样就会得到数组中元素的个数
    int total = SumOfElements(A);
    printf("Sum of elements = %d\n",total);
    printf("Main - Size of A = %d,size of A[0] = %d\n",sizeof(A),sizeof(A[0]));

    system("pause");
    return 0;
}

指针和字符数组

NULL字符的ASCII的值是0,因为C里面的字符串必须以NULL结束

#include<stdio.h>
#include<stdlib.h>

int main()
{
    char C[5];
    C[0] = 'J';
    C[1] = 'O';
    C[2] = 'H';
    C[3] = 'N';
    C[4] = '\0';
    printf("%s",C);

    getchar();
    return 0;
}

strlen函数不会把null算入在内

当把字符数组赋值给字符指针,实际上是把字符数组的首地址告诉指针

#include<stdio.h>
void print(char* C)
{
    int i = 0;
    while(C[i] != '\0')
    {
        printf("%c",C[i]);
        i++;
    }
    printf("\n");
}
int main()
{
    char C[20] = "Hello";
    print(C);

    getchar();
    return 0;
}

指针和二维数组

指针和多维数组

多维数组本质上是数组的数组

数组基本上可以理解为同类型事物的集合,多维数组基本上可以理解为数组的集合

当仅使用数组名的时候,它会返回数组首元素的指针

print B //400

print *B //400

print B[0] //400

print &B[0][0] //400

B返回一个指向一维数组的指针,而*B返回一个指向整型的指针 

当我们只是打印地址的时候,一维数组B[0]和B[0]的首元素的起始地址是一样的,所以会打印相同的地址

arr[2][3][4],相当于一个三维数组有两个数组,这两个二维数组里面各自有三个数组,这三个数组各自里面再有四个数组

解引用就是 当前变量存取的值,如果*p是指向数组,则值就是首地址,如果是指向数据,则就是值。

#include<stdio.h>
#include<stdlib.h>
int main()
{
    int C[3][2][2]={{{2,5},{7,9}},{{3,4},{6,1}},{{0,8},{11,13}}};
    printf("%d %d %d %d",C,*C,C[0],&C[0][0]);
    printf("%d\n",*(C[0][0]+1));

    system("pause");
    return 0;
}

多维数组作为参数传给函数

指针和动态内存-栈vs堆

栈,用来存放函数调用的所有信息和所有局部变量

局部变量是在函数内部声明的,只在函数执行期间存活

不在函数中声明的变量,它们的生命周期贯穿整个应用程序

任何时候都是栈顶的函数在执行

应用程序的堆不是固定的,它的大小在应用程序的整个声明周期是可变的

这里所说的堆和数据结构中的堆没有关系,此处的堆只是用来描述空闲的内存池

栈也是一种数据结构,但是栈区实际上就是栈这种数据结构的一种实现,堆并不是这样

内存在栈上的分配和销毁有一定的规则 ,当一个函数被调用的时候,它被压入堆栈,当它结束的时候,弹出堆栈。

如果变量是在栈上分配的,我们不能操作变量的范围

不能操控变量的范围,就是比如说定义了一个可变数组在栈中,而在程序运行中栈的内存不会增长,因此你的数组很有可能因为长度过长而造成栈溢出

应用程序的堆不是固定的,它的大小在应用程序的整个声明周期是可变的,也没有特定的规则来分配和销毁相应的内存

堆也被称为动态内存,使用堆内存意味着动态内存分配

堆也是一种数据结构,但是与c中的堆不一样

任何使用malloc分配的内存,最终通过调用free进行释放

c++用new来代替malloc ,delete来代表free

指针和动态内存

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/313208.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

黑马苍穹外卖学习Day5

文章目录 Redis学习Redis简介准备工作Redis常用数据类型介绍各数据类型的特点Redis常用命令字符串操作命令哈希操作命令列表操作命令集合操作命令有序集合操作命令通用操作命令 在Java中操作Redis导入Spring Data Redis坐标配置Redis数据源编写配置类&#xff0c;创建RedisTemp…

Golang基础入门及Gin入门教程(2024完整版)

Golang是Google公司2009年11月正式对外公开的一门编程语言&#xff0c;它不仅拥有静态编译语言的安全和高性能&#xff0c;而 且又达到了动态语言开发速度和易维护性。有人形容Go语言&#xff1a;Go C Python , 说明Go语言既有C语言程序的运行速度&#xff0c;又能达到Python…

【贪心】一手顺子

/** 贪心&#xff1a;将一个数当成一个组中最小的数&#xff0c;在根据该最小数找其它数。* 思路&#xff1a;将hand进行分组&#xff0c;假设hand长度为 n&#xff0c;必须n % groupSize 0才可以分组&#xff0c;否则返回false&#xff0c;* 使用哈希表记录每个数出现…

ffmpeg命令增加headers参数解决http请求ts返回404 not found问题的解决方法:-headers、-an

最近项目上遇到一个问题&#xff0c;用ffmpeg请求录制一个m3u8的实时流成为mp4文件的时候&#xff0c;命令返回404错误&#xff1a; 但是有一个很奇怪的现象&#xff0c;就是ffmpeg请求不到的&#xff0c;VLC却能正常播放&#xff0c;对比一下抓包&#xff1a; 那么既然就差别…

用机器学习方法来预测设备故障

最近做了一个项目&#xff0c;根据设备的状态&#xff0c;来判断设备是否有故障&#xff0c;这里总结一下所用到的数据探索&#xff0c;特征工程以及机器学习模型等方法。考虑到项目数据的敏感性&#xff0c;这里我以网上找到的一个公开数据集UCI Machine Learning Repository作…

基于STM32的温室大棚环境检测及自动浇灌系统设计

需要全部资料请私信我&#xff01; 基于STM32的温室大棚环境检测及自动浇灌系统设计 一、绪论1.1 研究背景及意义1.2 研究内容1.3 功能设计 二、系统方案设计2.1 总体方案设计 三、系统硬件设计3.1 STM32单片机最小系统3.2 环境温度检测电路设计3.3 土壤湿度检测电路设计3.4 光…

FineBI实战项目一(23):订单商品分类词云图分析开发

点击新建组件&#xff0c;创建订单商品分类词云图组件。 选择词云&#xff0c;拖拽catName到颜色和文本&#xff0c;拖拽cat到大小。 将组件拖拽到仪表板。 结果如下&#xff1a;

企业微信forMAC,如何左右翻动预览图片

1、control commandshifd 进入企业微信的debug调试模式 2、按照如下步骤选择 3、重启企业微信

uniapp微信小程序投票系统实战 (SpringBoot2+vue3.2+element plus ) -我参与的投票列表实现

锋哥原创的uniapp微信小程序投票系统实战&#xff1a; uniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )_哔哩哔哩_bilibiliuniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )共计21条视频…

欧洲高性能计算联合企业豪掷2000万欧元采购量子计算机

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 编辑丨慕一 编译/排版丨琳梦 深度好文&#xff1a;945字丨8分钟阅读 近日&#xff0c;欧洲高性能计算联合企业&#xff08;EuroHPC JU&#xff09;启动了一项重要计划&#xff0c;旨在显著提…

MOOSE相关滤波跟踪算法(个人学习笔记)

MOOSE 论文标题 “Visual Object Tracking using Adaptive Correlation Filters” 原文地址 用滤波器对目标外观进行建模&#xff0c;并通过卷积操作来执行跟踪。 参考阅读&#xff1a; 目标跟踪经典算法——MOSSE&#xff08;Minimum Output Sum Square Error&#xff09…

电容的基础知识

一、电容单位 电容亦称作“电容量”&#xff0c;是指在给定电位差下的电荷储藏量&#xff0c;记为C&#xff0c;国际单位是法拉&#xff08;F&#xff09;。在国际单位制里&#xff0c;电容的单位是法拉&#xff0c;简称法&#xff0c;符号是F&#xff0c;由于法拉这个单位太大…

Zynq 电源

ZYNQ芯片的电源分PS系统部分和PL逻辑部分&#xff0c;两部分的电源分别是独立工作。PS系统部分的电源和PL逻辑部分的电源都有上电顺序&#xff0c;不正常的上电顺序可能会导致ARM系统和FPGA系统无法正常工作。 PS部分的电源有VCCPINT、VCCPAUX、VCCPLL和PS VCCO。 VCCPINT为PS内…

canvas绘制流动的蚂蚁线(图文示例)

查看专栏目录 canvas示例教程100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

提高iOS App开发效率的方法

引言 随着智能手机的普及&#xff0c;iOS App开发成为越来越受欢迎的技术领域之一。许多人选择开发iOS应用程序来满足市场需求&#xff0c;但是iOS App开发需要掌握一些关键技术和工具&#xff0c;以提高开发效率和质量。本文将介绍一些关键点&#xff0c;可以帮助你进行高效的…

自动化测试框架pytest系列之8个常用的装饰器函数

自动化测试框架pytest系列之基础概念介绍(一)-CSDN博客 自动化测试框架pytest系列之21个命令行参数介绍(二)-CSDN博客 自动化测试框架pytest系列之强大的fixture功能&#xff0c;为什么fixture强大&#xff1f;一文拆解它的功能参数。(三)-CSDN博客 接上文 3.5 pytest的8…

Agisoft Metashape 基于影像的外部点云着色

Agisoft Metashape 基于影像的外部点云着色 文章目录 Agisoft Metashape 基于影像的外部点云着色前言一、添加照片二、对齐照片三、导入外部点云四、为点云着色五、导出彩色点云前言 本教程介绍了在Agisoft Metashape Professional中,将照片中的真实颜色应用于从不同源获取的…

监督学习 - 逻辑回归(Logistic Regression)

什么是机器学习 逻辑回归&#xff08;Logistic Regression&#xff09;虽然名字中包含"回归"一词&#xff0c;但实际上是一种用于解决分类问题的统计学习方法&#xff0c;而不是回归问题。它是一种线性模型&#xff0c;常用于二分类问题&#xff0c;也可以扩展到多分…

【EI会议征稿通知】2024年图像处理与人工智能国际学术会议(ICIPAI2024)

2024年图像处理与人工智能国际学术会议&#xff08;ICIPAI2024&#xff09; 2024 International Conference on Image Processing and Artificial Intelligence&#xff08;ICIPAI2024&#xff09; 2024年图像处理与人工智能国际学术会议&#xff08;ICIPAI2024&#xff09;将…

python 爬虫 生成markdown文档

本文介绍的案例为使用python爬取网页内容并生成markdown文档&#xff0c;首先需要确定你所需要爬取的框架结构&#xff0c;根据网页写出对应的爬取代码 1.分析总网页的结构 我选用的是redis.net.com/order/xxx.html (如:Redis Setnx 命令_只有在 key 不存在时设置 key 的值。…