C语言程序与设计——指针地址与main函数

news2024/11/25 8:21:56

指针变量

在C语言中,最重要的就是对于指针和地址的理解,因为C语言是更接近底层的编程语言,所以它可以允许开发者对内存操作,这也是区别于其它编程语言的一个重要特性。
如何对内存进行操作呢。我们知道在编程过程中,在任何语言中,我们在定定义一个变量的过程中,实际上就是向操作系统申请了一块内存,但由于其它编程语言不支持我们对于内存进行操作,所以我们只知道申请了一块内存,但不知道该位置在哪。由于C语言支持我们对于内存的操作,所以我们可以通过在变量前加一个取地址符&,得到该内存的地址,数组的话无需加取地址符。

#include<stdio.h>
int main(){
    int a[5];
    int b;
    printf("&b = %p, sizeof(&b) = %lu\n", &b, sizeof(&b));
    printf("a[0] = %p\n", a);
    printf("a[1] = %p\n", a + 1);
    printf("a[2] = %p\n", a + 2);
    printf("a[3] = %p\n", a + 3);
    printf("a[4] = %p\n", a + 4);
}

运行结果
>>&b = 0x7fffe87408ec, sizeof(&b) = 8
a[0] = 0x7fffe87408f0
a[1] = 0x7fffe87408f4
a[2] = 0x7fffe87408f8
a[3] = 0x7fffe87408fc
a[4] = 0x7fffe8740900

可以看到整型数组的地址间隔刚好为4,也就是说明整型变量大小是四个字节。而且指针的大小是8个字节。

指针的大小
在我所演示的运行环境是在64位操作系统下运行的,64bit刚好是8字节,也就是说如果在32位操作系统下运行该程序的话sizeof(&b)会是4字节

  • 指针的大小是与系统环境相关的
  • 以int为例,int占用四个字节,在取地址时从相关地址的首地址开始
  • 在一个32bit操作系统中,地址最多为4GB,所以假设插入一个8GB的内存条则会有另外4GB无法使用

变量的地址

指针变量也是变量,也就说,指针变量同样也有地址。由此,我们就可以对数组的各个地址取地址符,这样就构成了二维数组。

#include<stdio.h>

int main(){

    int a;
    int *p = &a;
    int arr[3][3];
    printf(" &a = %p\n p = %p\n &p = %p\n", &a, p, &p);
    printf(" arr[0][0] = %p, sizeof(arr[0][0]) = %lu\n", arr, sizeof(&arr));
    printf(" arr[1][0] = %p, sizeof(arr[1][0]) = %lu\n", arr + 3, sizeof(arr + 3));
    printf(" arr[1][0] = %p, sizeof(arr[2][0]) = %lu\n", &arr + 1, sizeof(arr + 3 + 3 + 1));

}

  
 运行结果
 >> &a = 0x7fff350f5c54
 p = 0x7fff350f5c54
 &p = 0x7fff350f5c58
 arr[0][0] = 0x7fff350f5c60, sizeof(arr[0][0]) = 8
 arr[1][0] = 0x7fff350f5c84, sizeof(arr[1][0]) = 8
 arr[1][0] = 0x7fff350f5c84, sizeof(arr[2][0]) = 8

理解了双重指针以及二维数组之后,那么就可以尝试高维数组的实现形式。

所以在scanf(“%d”, &n);这行代码中,我们传入的是地址,因为我们要改变的是n所代表的这块内存上的值,所以需要找到内存的所在地址然后存入数据。

函数指针

在之前函数的章节,已经涉及到了函数指针,但只是把函数作为传入参数的形式,下面我们将演示函数指针的声明形式

#include<stdio.h>

int add(int a, int b){
    return a + b;
}
int main(){
    int (*func)(int, int);
    func = add;
    printf("%d", func(1,1));
}
#include<stdio.h>

int add(int a, int b){
    return a + b;
}
int main(){
    typedef int (*func)(int, int);
    func f = add;
    printf("%d", f(1, 1));
}

可以看到我们使用了两种方式定义了函数指针。可以看到以第一种是直接声明的了一个函数指针,而后将指针指向了add()函数,那么第二种的话用到了一个关键字typedef,而后func变成了一个类型的样子,随后定义了f指针指向了add()函数。二者的定义形式的区别就是

声明一个函数指针变量: int (*add)(int, int);
定义一个函数指针类型: typedef int (*add)(int, int);

Main函数

我们知道在C语言中,一个程序运行必须要有main函数,但是我们在使用main函数中,基本都是无参数的形式,但实际上的main函数有三种形式,如下。下面就简单了解一下main函数的其他两种形式

int main();
int main(int argc, char *argv[]);
int main(int argc, char *argv[], char **env);

参数解释:
argc: 命令行参数个数(例如 ls -al al就是参数)
*argv[ ]:命令行内容(注意这是一个二位数组)
**env:环境变量

#include<stdio.h>

void output(int argc, char *argv[], char **env){
    printf("argc = %d\n", argc);
    for(int i = 0; i < argc; i++){
        printf("argv[%d] = %s\n ", i, argv[i]);
}

int main(int argc, char *argv[], char **env){
    output (argc, argv,env);
    return 0;
}

在这里插入图片描述
可以看到示例 ./a.out -a -l -s。其中作为参数全部传入了程序中,值得一提的是./a.out也作为了一个参数传入了,也就是说程序在运行时至少会有一个命令行参数。我们也不难发现空格是参数的分隔符,但是我们可以通过加\转义字符,使其可以把空格传入。

#include<stdio.h>

void output(int argc, char *argv[], char **env){
    printf("argc = %d\n", argc);
    for(int i = 0; i < argc; i++){
        printf("argv[%d] = %s\n ", i, argv[i]);
    }
    for(int i = 0; env[i]; i++){
        printf("env[%d] = %s\n", i, env[i]);
    }
}


int main(int argc, char *argv[], char **env){
    output (argc, argv,env);
    return 0;
}

在这里插入图片描述
可以看到env参数包含了很多我们的环境变量,包括用户路径语言等等。这些都是操作系统为我们提供的接口允许我们可以做在操作系统中做一些底层的操作。

main()返回值

在我们初学C语言时就接触了main()函数,我们可以不用返回值,但是又会经常见到return 0。那么main的返回值是返回给谁,又有什么作用呢?从函数上来讲,当然是谁调用就返回给谁,该函数是操作系统调用的,所以就是返回给操作系统的。
我们可以通过echo $?的命令查看上一次运行是不是成功运行,如果返回值为0,代表执行失败。如果是1则是成功执行,所以说可能对于我们来讲程序的功能是成功执行的,但是对于操作系统来讲我们的程序没有执行成功。所以我们应尽量在主函数中加入返回值。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软件设计师:11-结构化开发与UML

结构化开发&#xff08;3-4分&#xff09; 一、模块化 二、耦合&#xff08;背&#xff09; 三、内聚&#xff08;背&#xff09; 四、设计原则&#xff08;背&#xff09; 五、系统文档 六、数据流图 数据流的起点或终点必须有一个是加工 判断依据&#xff1a; 1、…

CTF之GET和POST

学过php都知道就一个简单传参&#xff0c;构造payload:?whatflag得到 flag{3121064b1e9e27280f9f709144222429} 下面是POST那题 使用firefox浏览器的插件Hackbar勾选POST传入whatflag flag{828a91acc006990d74b0cb0c2f62b8d8}

【TI毫米波雷达】官方工业雷达包的生命体征检测环境配置及避坑(Vital_Signs、IWR6843AOPEVM)

【TI毫米波雷达】官方工业雷达包的生命体征检测环境配置及避坑&#xff08;Vital_Signs、IWR6843AOPEVM&#xff09; 文章目录 生命体征基本介绍IWR6843AOPEVM的配置上位机配置文件避坑上位机start测试距离检测心跳检测呼吸频率检测空环境测试 附录&#xff1a;结构框架雷达基…

js,uniapp,vue,小写数字转化为大写

应用场景&#xff1a; 把1、2、3&#xff0c;转为一、二、三 方法&#xff1a; retBigSrt(num) {const changeNum [零, 一, 二, 三, 四, 五, 六, 七, 八, 九]const unit [, 十, 百]num parseInt(num)const getWan (temp) > {const strArr temp.toString().split().re…

Github项目推荐-ChatGPT-Admin-Web

项目地址 https://github.com/AprilNEA/ChatGPT-Admin-Web 项目简介 通过api接入大模型&#xff0c;并基于此封装了一层用户管理的功能&#xff0c;适合团队内使用。 项目截图

瑞吉外卖实战学习-17、用户地址簿相关功能

用户地址簿相关功能 效果图1、根据规则创建相关文件2、新增收货地址接口3、列表查询页面以及设置默认地址 效果图 1、根据规则创建相关文件 2、新增收货地址接口 获取到传入的数据然后将id添加进去&#xff0c;然后存储到数据库 3、列表查询页面以及设置默认地址 list接口&am…

C顺序表:通讯录

目录 前言 通讯录数据结构 通讯录初始化 查找名字 增加联系人 删除联系人 展示所有联系人 查找联系人 修改信息 销毁通讯录 完整通讯录代码 前言 数据结构中的顺序表如果已经学会了&#xff0c;那么我们就可以基于顺序表来完成一个通讯录了 通讯录其实我们使用前…

1.0-spring入门

文章目录 前言一、版本要求二、第一个spring程序1.引入pom2.代码部分2.1 spring bean2.2 springContext.xml2.3 测试2.4 执行结果 总结 前言 最近想要系统的学习下spring相关的框架,于是乎,来到了B站(真是个好地方),spring会专门开一个专栏出来,记录学习心得,与大家共勉。 Spri…

[每天一道面试题] HTTP,FTP,TFTP的底层实现协议是什么

HTTP、FTP和TFTP等这些协议都是属于互联网协议网络层模型中的应用层协议。它们的底层实现主要依赖于传输层的两种协议—— TCP(传输控制协议) 和 UDP(用户数据报协议)。 HTTP: 超文本传输协议(HTTP)通常在TCP协议的基础上操作。HTTP用于在网络上传输超文本&#xff0c;是万维网…

【Redis 知识储备】读写分离/主从分离架构 -- 分布系统的演进(4)

读写分离/主从分离架构 简介出现原因架构工作原理技术案例架构优缺点 简介 将数据库读写操作分散到不同的节点上, 数据库服务器搭建主从集群, 一主一从, 一主多从都可以, 数据库主机负责写操作, 从机只负责读操作 出现原因 数据库成为瓶颈, 而互联网应用一般读多写少, 数据库…

云仓酒庄旗下雷盛红酒入驻香港星怡SingLa餐厅共绘美食美酒新篇章

近日&#xff0c;云仓酒庄旗下品牌雷盛红酒正式入驻香港餐厅星怡SingLa&#xff0c;这一跨界合作不仅为香港市民和游客带来了全新的味蕾享受&#xff0c;也标志着美食与美酒文化的很好结合&#xff0c;共同绘就了一幅精彩绝伦的美食美酒新篇章。 云仓酒庄一直以来都致力于为消费…

MySQL基础练习题:创建数据库

这部分主要是为了帮助大家回忆回忆MySQL的基本语法&#xff0c;数据库来自于MySQL的官方简化版&#xff0c;题目也是网上非常流行的35题。这些基础习题基本可以涵盖面试中需要现场写SQL的问题。 创建数据库 在开始练习之前&#xff0c;我默认你的电脑上是没有本系列练习题需要…

项目管理与经济决策(项目投资经济决策)

1.现金流量 流出系统的现金称为现金流出(CO) 流入系统的现金称为现金流入(CI) 现金流入&#xff0d;现金流出&#xff1d;净现金流量(NCF) 构成现金流量的基本因素&#xff1a;投资、&#xff08;付现&#xff09;成本、 &#xff08;现金&#xff09;收入、税金、利润等&a…

ICLR 2024 | 联邦学习后门攻击的模型关键层

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 新建了免费的人工智能中文站https://ai.weoknow.com 新建了收费的人工智能中文站https://ai.hzytsoft.cn/ 更多资源欢迎关注 联邦学习使多个参与方可以在数据隐私得到保护的情况下训练机器学习模型。但是由于服务器无法…

Java初始——IDEA-web的启动

Tomcat 文件夹作用 bin 启动 关闭的脚本文件 conf 配置 lib 依赖的jar包 logs 日志 temp 临时文件 webapps 存放的网站 Maven 1.在javaweb中&#xff0c;需要使用大量的jar包&#xff0c;手动导入 2.Maven 架构管理工具 核心&#xff1a;约定大于配置 必须按照规则 web idea-we…

【ELK】搭建elk日志平台(使用docker-compose),并接入springboot项目

1、环境搭建 前提条件&#xff1a;请自行安装docker以及docker-compose环境 version: 3 services:elasticsearch:image: elasticsearch:7.14.0container_name: elasticsearchports:- "9200:9200"- "9300:9300"environment:# 以单一节点模式启动discovery…

Git 配置BCompare工具

一、Git配置BCompare工具 1、安装BCompare工具 下载BCompare安装包&#xff0c;打开安装包直接安装即可&#xff0c;如下&#xff1a; 2、禁止BCompare访问网络 网络进出站进行配置&#xff0c;限制BCompare访问网络&#xff0c;如果不进行上网限制&#xff0c;可能存在被封的…

CloudCompare 点云工具

CloudCompare 点云工具 1. CloudCompare简介1.1 CloudCompare下载 2. CloudCompare安装 1. CloudCompare简介 CloudCompare 是一款开源的三维点云处理软件&#xff0c;它提供了一系列功能来处理、查看和分析三维点云数据。这个软件可以用于许多不同的应用领域&#xff0c;包括…

OKR应用层级与试点部门选择:管理层与员工层的应用探讨

OKR&#xff08;Objectives and Key Results&#xff09;作为一种高效的目标管理工具&#xff0c;其应用层级的选择对于企业的实施效果至关重要。在管理层和员工层之间&#xff0c;并没有绝对的先后顺序&#xff0c;而是需要根据企业的具体情况和需求进行灵活应用。同时&#x…

题目:【序列中删除指定数字】【变种水仙花数】【数组串联】【交换奇偶位】【offsetof宏的实现】

题目一:序列中删除指定数字 #include <stdio.h>int main(){int a0;int arr[50]{0};int c0;scanf("%d",&a);for(int i0;i<a;i){scanf("%d",&arr[i]);//输入a个值}scanf("%d",&c);//输入要删除的数据int i0;int j0;for(i0;i&…