`

赋值操作符的思考

 
阅读更多

         我要说的是一个小问题,感觉写在博客里面比较好。以后看到了可以回忆警示一下。

    问题是这样的:在Java中数组之间能不能通过数组名直接赋值,为什么?

                             在C中数组之间能不能通过数组名直接赋值,为什么

我们先来分析C语言中的情况:

        char arr[3]={'a','b','c'};
	char arrB[3]=arr;    //错的。
	int intArr[3]={1,2,3};
	int intArr2[3]=intArr;   //错的。

      原因很简单,在C语言中数组名相当于一个引用(C++中的引用),由于数组名不是一个变量,所以是不能作为赋值操作符的左值的。举个极端的例子,就像1++;和1=2;肯定是非法的一样(至于深层次的原因,可能是因为C语言为了安全性所做的规定)。

 

但是注意了在C语言中,以下却是可以的:

        char *p="hello";
	char *pB=p;
	printf("%s\n",pB);
//输出结果:
hello

      原因也很简单,“hello”在常量区,p指针保存一个地址指向了"hello"。将p的值赋值给pB也仅仅就是将这个字符串地址的值赋值给了pB。pB是一个指针变量可以作为赋值操作符的左值,所以他接受到了“hello”的地址。

     所以,此时的内存布局是:p和pB两个指针所存储的值是一样的,都是“hello”在常量区的地址。也就是常说的p和pB指向了同一块内存。

 

下来看一下Java环境下的分析:

public class Son{
	public static void main(String args[]){
		int arr[]={1,2,3};
		int arrB[]=arr;
		arrB[0]=5;
		System.out.println(Arrays.toString(arr));
	}
}
//运行结果:
[5, 2, 3]

     可见在Java环境中,采用数组名实现数组之间的赋值是可行的。原因也很简单,在Java中都是值传递,Java中的引用相当于C中的指针。所以arr和arrB是指向了同一块堆。是不是和上面那个C的例子很相像。

 

     最后说一下,在C中结构体是可以通过结构体名相互赋值的:

typedef struct Node{
	int value;
}node;
int main()
{
	node node1={3};
	node node2=node1;
	printf("%d\n",node2.value);

	node2.value=8;
	printf("%d\n",node1.value);
	
	system("pause");
	return 0;
}
//输出结果:
3
3

    我们发现结果竟然不是3和8,所以结构体通过结构体名进行赋值就是简单的值传递的。node1和node2在堆内存中开辟了两个空间,各自是独立的。仅仅是将node1的成员的值赋值给了node2相应的成员。

 

     最后看一个我经常容易忽视的问题:

        char *p="hello";
	char *pB=p
	pB[1]='a';
	printf("%s\n",pB);

 猜猜上面会输出什么?

 答案:发生中断,报错。

原因分析:“hello”是在常量区呀,p只是个指针,并没有给p分配用于存储“hello”的空间,所以p和pB同时指向了常量区的"hello"。常量区是不能修改的。所以报错。

 

解决办法:

        char *p=(char*)malloc(sizeof("hello"));
	memcpy(p,"hello",sizeof("hello"));
	char *pB=p;

	pB[2]='a';
	printf("%s\n",p);
	printf("%s\n",pB);

 此时,p拥有了自己的存储"hello"的内存空间(在堆区),但是pB没有。pB仅仅就是指向了p的那块内存。所以可以说pB就是个穷指针。

分享到:
评论

相关推荐

    c程序设计part3.ppt

    赋值操作符需要特别注意,因为它涉及到对象的深拷贝和浅拷贝问题,以及可能的自我赋值情况,所以在重载时需要特别小心。 总的来说,多态性是面向对象编程中一个强大的工具,它通过提供通用的接口处理不同类型的数据...

    序列点在C语言表达式求值中的作用.pdf

    如果没有序列点的概念,就很难解释为什么表达式中的自增操作符(具有较高优先级)会在这个例子中后于赋值操作符求值。 逻辑与操作符&&和逻辑或操作符II也存在序列点,以支持其“短路”特性。逻辑与操作符&&在求值...

    Swift Programming Language ios

    Swift语言还包括了基本操作符,比如赋值操作符、算术操作符、余数操作符、增量和减量操作符、逻辑操作符和范围操作符等,以支持数值和逻辑运算。同时,Swift支持字符串和字符的操作,包括字符串插值、字符串比较、...

    Absolute C++中文版(原书第2版)-完美的C++教程,文档中还包含英文版

    14.2.1 派生类中的赋值操作符和复制 构造函数 426 14.2.2 派生类的析构函数 426 14.2.3 保护继承和私有继承 436 14.2.4 多继承 437 第15章 多态与虚函数 442 15.1 虚函数基础 442 15.1.1 后绑定 442 15.1.2 ...

    像计算机科学家一样思考(C++版)-201512280836561

    - 讲解了操作符,如算术、比较和逻辑操作符,以及它们的优先级。 - 介绍了如何组合使用操作符和变量来表达复杂的计算。 第3章 函数: - 讨论了浮点数和类型转换,如double到int。 - 介绍了一些数学函数,如平方根和...

    C++ Primer学习笔记.doc

    笔记中还提到了一种利用编译错误预防常见编程错误的方法,即通过改变条件表达式顺序来避免误用赋值操作符等于号。 第五章简要介绍了类的概念,成员函数被定义为类的一部分,有时被称为“类方法”。学习笔记中提醒了...

    C指针练习.docx

    解释:在C语言中,&操作符是 取地址运算符,可以获取变量的内存地址。*&a表示获取a的地址,然后将其赋值给point指针变量。 2. 若有说明:int *p, m = 5, n; 以下正确的程序段是: 答案:A. p = &n; 解释:在C语言...

    《thinkjava》

    3. 变量和操作符:包括变量的声明和赋值,状态图,打印变量,以及算术操作符。在这一部分中,读者可以学习到如何在Java中存储和操作数据。 4. 输入输出操作:利用System类和Scanner类进行输入输出操作,介绍了程序...

    odesk javascript

    2. **操作符与表达式**:包括算术操作符、比较操作符、逻辑操作符,以及三元条件运算符。理解这些操作符的用法对于编写逻辑复杂的代码至关重要。 3. **函数**:JavaScript中的函数是可重用的代码块,可以接受参数并...

    Learning Penetration Testing with Python pdf 0分

    - **操作符**:介绍Python中的比较操作符、赋值操作符、算术操作符、逻辑操作符等。 ### 其他知识点 - **攻击技术**:书中可能包含如何使用各种工具和脚本进行网络攻击的知识。 - **安全攻防**:涵盖安全测试与...

    effective c++中文第三版

    3. **优先考虑复制构造函数和赋值操作符**:为了确保对象的正确复制和赋值,作者建议程序员显式定义复制构造函数和赋值操作符,尤其是当类包含资源管理逻辑时。 4. **使用const正确地表达意图**:通过合理地使用...

    verilog hdl教程135例

    3. **操作符**:包括算术操作符、逻辑操作符、比较操作符和位操作符等,如+、-、&、|、<、>、~等,用于实现逻辑功能。 4. **进程与语句**:如always块用于描述时序逻辑,initial块用于初始化值,case语句和if-else...

    2021-2022计算机二级等级考试试题及答案No.1574.docx

    - 所有的二元数学操作符都有相应的增强赋值操作符,例如 `+=`、`-=` 等。 - 并非所有的数学运算都需要引用第三方库 `math`,Python 内置了很多常用的数学运算功能。 ### 5. 运算符优先级 - 表达式 `25\2` 中,反...

    第六节 面向对象编程(2).docx

    创建 `Person` 对象并设置其属性值后,通过赋值操作符 `=` 可以将一个对象赋值给另一个对象,如 `b = a;`。在这种情况下,`b` 和 `a` 指向相同的内存地址,因此修改 `b` 的属性会影响到 `a`。 关于对象在内存中的...

    高级Bash脚本编程指南(中文版)

    操作符也是脚本编程中的重要元素,包括算术操作符、关系操作符和逻辑操作符等。 当学习者对基础有了一定掌握之后,可以进入更高级的学习阶段,例如变量重游,这涉及到操作字符串、参数替换、声明变量类型以及变量的...

    C++Primer 中文版第五版 部分习题代码 第2章

    在本章节中,读者将接触到C++的基础知识,包括但不限于变量、数据类型、操作符、表达式、控制流以及函数的使用。下面将对这些知识点进行详细阐述。 首先,变量是程序中存储数据的容器。在C++中,我们需要先声明变量...

    java 编程入门思考

    5.2 Java访问指示符 5.2.1 “友好的” 5.2.2 public:接口访问 5.2.3 private:不能接触 5.2.4 protected:“友好的一种” 5.3 接口与实现 5.4 类访问 5.5 总结 5.6 练习 第6章 类再生 6.1 合成的语法 6.2 继承的...

Global site tag (gtag.js) - Google Analytics