IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 地址与值的更改 -> 正文阅读

[C++知识库]地址与值的更改

????????说到地址,在C语言中一般都与指针挂钩,我们可以利用指定的指针变量来存储特定的内存块的首地址。指针可以可以指向的变量包括整型变量、浮点型变量、结构体变量、指针变量乃至字符串和函数,因为这些事物都是占据内存空间的实体。所以,指针的便利之处在于其能够储存某个变量的首地址,并通过首地址访问或修改在这个内存空间的值。下面举一个例子:

//代码清单1
#include<stdio.h>
#include<string.h>
int main()
{
	char str[25]="Be stronger,be helpful!";
	printf("%s\n", str);
	char *str_ptr = str;
	str_ptr[strlen(str) - 1] = '.';
	printf("%s", str);
	return 0;
}

执行结果是什么呢?如图:

????????在第5行代码中,我们定义了一个字符串并往它里面添加了一些字符,然后我们在第7行定义了一个字符指针并且用 str[] 数组的首地址 str 为它赋初值,之后在第8行通过 str_ptr 将 str[] 字符数组的最后一个字符由 ‘ ! ’ 替换为 ‘ . ’ ,通过6、9行的输出语句分别输出被替换字符前后储存在 str[] 内的字符串。我们发现,通过这样的操作,我们的确修改了 str[] 内的字符串。

? ? ? ? 与此类似地,我们可以将字符串修改的这一操作推广到各种变量,在其中,掌握指向指针变量的指针也是很重要的。我们举一个例子:

//代码清单2
#include<stdio.h>
#include<string.h>
int main()
{
	char **str_ptr = NULL;
	char *str[2] = { "Be stronger,be helpful!","Hold your dream." };
	str_ptr = str;
	printf("%s\n", str_ptr[0]);
	printf("%s", str_ptr[1]);
	return 0;
}

在第5行代码中,我定义了一个二重指针 str_ptr ,而在第6行代码中则定义了一个含有两个字符指针作为元素的一个一维数组,第7行中将 str 作为初值赋给了 str_ptr 。为什么能将一个一维数组的首地址赋给一个二重指针呢?原因只有一个,str 此时是一个“二重指针常量”,我找不到更好的词来说明 str 的性质了,但显然,我们将常量值赋给变量,这是很合理的一种想法。我们还可以这样来理解这个“二重指针常量”:str[]中的元素本身就是字符指针,故 str[0]、str[1] 就已是普通的字符指针了,可以理解为“一重指针常量”,这种字符指针指向普通的字符串;而 str[] 又是有着两个元素的数组,str 表示的正是它的首地址,故 str 相对于自身元素而言又是“一重指针常量”,由于其元素本身已是“一重指针常量”,我们可以认为相对于普通的指针,str 可以理解为“二重指针常量”。至于三重指针,也是一样的道理,不过更加复杂了。

????????另外,指针的应用显然不止这么简单,如果我们在为函数传参数时,想要为想要改变传递的参数的值,我们需要这个参数的地址,举一个例子:

//代码清单3
#include<stdio.h>
typedef struct stu
{
	char id[3];
	char name[10];
}stu;
int modify(stu *stud)
{
	strcpy(stud->id , "7");
	strcpy(stud->name, "Log");
	return 0;
}
int main()
{
	stu student;
	stu *stude = &student;
	strcpy(student.id, "6");
	strcpy(student.name, "Rog");
	printf("%s :%s\n", student.id, student.name);
	modify(stude);
	printf("%s :%s", student.id, student.name);
	return 0;
}

结果为:

可以看到, 通过将 modify() 的形参设置为 stu* 类型,我们在第20行将同类型的变量 stude 传递给了 modify() ,然后 student 的值的确在 modify() 函数内被改变了。那就要问了,如果我们不将指针 stude 传给这个函数,我们能直接将一个 stu 类型而非 stu* 类型的变量作为 modify() 的形参从而改变 student 的值吗?我们不妨试试:

//代码清单4
#include<stdio.h>
typedef struct stu
{
	char id[3];
	char name[10];
}stu;
int modify(stu stude)
{
	stu *stud = &stude;
	strcpy(stud->id , "7");
	strcpy(stud->name, "Log");
	return 0;
}
int main()
{
	stu student;
	strcpy(student.id, "6");
	strcpy(student.name, "Rog");
	printf("%s :%s\n", student.id, student.name);
	modify(student);
	printf("%s :%s", student.id, student.name);
	return 0;
}

结果为:

student 的值并没有改变,因此这种方法是行不通的。原因?

C语言使用一种被称为“按值”的机制,给函数传递参数。这是因为,当使用变量作为函数参数的时候,C语言并不是把变量的地址传给函数,而是传递变量的值。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??????????————《C语言实用之道》[美] Giulio Zambon 著? ? 潘爱民 译

因此,这串代码中,我们只是将 student 的值拷贝给了 modify() 的形参 stude ,当我们在第20行调用 modify() 的时候,实际上我们只是给它传了 student 的值,然后很快就将这个值给了 stude ,接下来在 modify() 中起作用的实际上是 stude ,而不是 student 。这样看来,student 和 stude 实际上是两个不同的变量,我们可以试验一下,只需将代码清单4的代码改为:

//代码清单5
#include<stdio.h>
typedef struct stu
{
	char id[3];
	char name[10];
}stu;
int modify(stu stude)
{
	stu *stud = &stude;
	strcpy(stud->id, "7");
	strcpy(stud->name, "Log");
	printf("stude's address:%p\n", &stude);
	return 0;
}
int main()
{
	stu student;
	strcpy(student.id, "6");
	strcpy(student.name, "Rog");
	printf("student's address:%p\n", &student);
	printf("%s :%s\n", student.id, student.name);
	modify(student);
	printf("%s :%s", student.id, student.name);
	return 0;
}

结果为:

在我的PC机上可以看到 student 和 stude 的确是被存储在不同的内存单元的,而这正说明了 student 和 stude 是两个不同的变量。

? ? ? ? 有的时候,我们也可以定义一个字符指针来达到行使字符数组的功能,例如:

//代码清单6
#include<stdio.h>
int main()
{
	char *str = "Be stronger,be helpful!";
	/*
	char *str = NULL;
	str = "Be stronger,be helpful!";
	*/
	//第7、8行的为str赋值的方式也是正确的
	
	/*
	char str[25];
	str = "Be stronger,be helpful!";
	*/
	//第13、14行的为str赋值的方式是错误的,
	//因为第13行定义的str[]数组被分配了内存,
	//str是这块内存的首地址,已经是一个常量了
	printf("%s", str);
	return 0;
}

结果为:

? ? ? ? 再说一下我们在每个程序中都必写的 main() 函数,它的完整形式为:

main(int argc,char *argv[])

?写一个小程序:

//代码清单7
#include<stdio.h>
int main(int argc, char *argv[])
{
	printf("当前文件为:%s", argv[0]);
	int iInt = atoi(argv[1]);
	printf("接收的第一个参数为: %d\n", iInt);
	iInt = atoi(argv[2]);
	printf("接收的第二个参数为: %d\n", iInt);
	iInt = atoi(argv[3]);
	printf("接收的第三个参数为: %d\n", iInt);
	printf("总共接收了 %d 个参数", argc - 1);
	return 0;
}

当然,它不能在编译器上运行,它是在控制台上运行的,接下来我将教你如何操作这个函数,我的运行环境是Visual Studio,我们先运行一下这个程序:

这是正常的,我们要的正是当前文件的路径,而编译器也只能给我们这个,接着程序便运行不下去了。得到了这个exe文件(可执行文件)路径,我们继续。

具体步骤为:

1、按下 Win+R 键

2、输入cmd

3、进入到要执行的exe文件所在目录

这里对第3个步骤进行详细讲解:

????????首先,我利用在编译器中执行一次的方法得到了相应源文件的可执行文件,并且在我的PC机中它的路径为:C:\Users\86187\source\repos\博客专用\Debug\博客专用.exe? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 那么,我需要在弹出的控制台窗口中输入 cd?C:\Users\86187\source\repos\博客专用\Debug ,同时按下Enter键,画面为:

接着依次输入exe文件的名称和随便三个数字:?博客专用 12?23?34? ,我们就得到了下图所示的结果:

?

????????可以看到,在控制台中我们看到了我们在源文件中写的代码清单7中的代码的执行结果。那么接下来,我讲一下 argv 和 argc 的意义,argc 默认值是1,代表只有数组 argv[] 的元素个数只有一个,即 argv[0] ,而 argv[0] 的意义大家想想自己是如何获取到自己的可执行文件路径的呢?没错,argv[0] 代表的正是由这个源文件生成的可执行文件的路径。说回来,argc 的大小代表着数组 argv[] 的元素个数,我们利用控制台执行了这个文件,输入了3个参数,分别为12、23、34,是没有用到输入函数如scnaf()、gets()的,这一点大家明确。另外,atoi() 函数可以将数字字符串转换成数字,atoi即alphabet to integer,想多了解可以戳这里

本篇完。


欢迎指正我的上一篇博客:递归实现双向链表

我的下一篇博客:待续

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-11 21:57:07  更:2022-03-11 21:59:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:57:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码