连续赋值?多变量初始化?变量初始化?赋值运算符?
目录
连续赋值
多变量初始化
不同类型的多变量初始化
多个变量初始化只用部分
变量初始化
初始化形式
字符串初始化
特定语句中初始化
多变量初始化
变量初始化省略缺省类型?
赋值运算符
=和==
不同的赋值运算符
赋值运算符前后的空格
连续赋值
赋值和相等比较的误用
一些古老的复合赋值运算符
连续赋值
C语言支持形如 i = j = k = 0简化了多个变量初始化。主流编程语言均支持,如C/C++/Java/C#/Python/Ruby/PHP 等。
- Swift将赋值运算的结果设定为空,对应于类型(),不支持连续赋值。
例如:a = b = 1会提示error: cannot assign value of type '()' to type 'Int'
多变量初始化
除了编程语言提供的初始化赋值对多个变量初始化,连续赋值同时初始化多个相同变量。这些基本的初始化类似于:
- int a = 1, b = 2;
- a = b = 1;
C/ObjC/C++/VB/Java都支持如上基本的多变量统一初始化方式。
除了上面,还有一些更舒适的初始化方式:多变量分别初始化方式。
- Swift和Rust提供tuple对多个变量初始化
例如let (x, y) = (1, 2)会将x赋值为1,y赋值为2. - Go语言提供形如 x, y := 1, 2 初始化x和y两个变量,也可以实现两个变量的快速交换,如 a, b = b, a
- Python可以直接用下面完成3个变量初始化:a, b, c = 1, 2, 3
- C# 7.0引入解构赋值,类似tuple的多变量初始化也可以轻松完成:
(int x, int y) = (10, 20);
(x, y) = (1, 2); - JS也提供解构赋值初始化多个变量,如下示例的x, y, z可以单独使用。
let { x, y, z } = { x: 1, y: 2, z: 3 }; - C++虽然提供tuple元组,但初始化方式并不像下面提到的方便。
不同类型的多变量初始化
有的时候,我们想要在一行代码中初始化两个不同类型的变量:int a = 1, double b = 3.14; 如果是类型放在变量前面的编程语言一般都不能支持,但类型放在类型后面的编程语言却很容易支持。
- C/ObjC/C++/Java/C# 均不能支持这种行为。
- Swift 可以实现:let a: Int = 1, b: Double = 3.14
- Go语言支持多个不同类型变量初始化,需要放在括号里面
var (
name string = "alex"
age int = 28
)
多个变量初始化只用部分
- 尽管类似Go语言提供多个变量同时初始化,但有时又不想多个变量都要用,只想用关心的。Go语言提供空白标识符"_"来隐藏变量,此变量又被称为匿名变量,不过不能输出匿名变量。
例如只想获取HTTP的status:
status, _ = 200, "HTTP request is OK"
变量初始化
尽管听起来,初始化是一件不复杂的事情,事实上初始化在不同编程语言里各藏玄机。
初始化形式
初始化无非就是变量名、初始值和类型(可选)的组合,不同编程语言提供了截然不同的形式。这里把声明也当做初始化的“前期“来分析,变量声明的格式就是变量初始化去掉初始化值。
- C/ObjC/C++/Java/C#
- 类型 变量 [= 初始值] [, 变量 = 初始值] ... ;
- int a = 1;
- C++11之前C++初始化(...)和{...}都可以,C++11之后统一用{}格式初始化
- int a{10}; 或者 int arr[] {1, 2, 3}; 特别的,{}默认初始化为0.
- C++20引入指派初始化器,可指定结构或类某个成员的初始化,其实C99早就有结构体指定初始化的方式。
- Student s{.sex = 'M', .age = 28};
- 类型 变量 [= 初始值] [, 变量 = 初始值] ... ;
- Python
- 不需要类型,使用 "变量 = 初始值"
- a = 1
- 不需要类型,使用 "变量 = 初始值"
- Go
- var 变量 [类型] = 初始值
- var a int = 1
- var 变量 [类型] = 初始值
- Rust
- let 变量 [: 类型] = 初始值;
- let a: i32 = 1;
- let 变量 [: 类型] = 初始值;
- JS
- let | var 变量 = 初始值;
- var不推荐,推荐用let.
let today = new Date();
- var不推荐,推荐用let.
- let | var 变量 = 初始值;
- Swift
- let | var 变量 [: 类型] = 初始值;
let a = 1
- let | var 变量 [: 类型] = 初始值;
- Shell
- 因支持命令和参数,变量名后面不能跟空格,需要用a=11, 不能用a = 11.
- 仓颉
- var | let 变量 [: 类型] = 初始值;
- VB
- Dim 变量名 As 数据类型 = 初始值
可以在变量名后面加上类型,例如name$代表字符串类型。 - VB还支持隐式声明,默认是变体类型,这种很不安全。可以在VB IDE环境菜单 --> "工具" --> "选项" --> "编辑器"中选择"要求变量声明"强制变量显式声明。
- VB还支持字符串定长初始化,例如 Dim str As String * 8 代表str字符串长度最大为8.
- Dim 变量名 As 数据类型 = 初始值
- Fortran
- <variable_type> :: <variable_name>
integer :: sum
- <variable_type> :: <variable_name>
- Pascal
- var 变量 : 类型 = 初始值
多个同类型可以一起声明,但一旦有初始化就只能是一个变量:var i, j : integer = 1 是不行的。
- var 变量 : 类型 = 初始值
- Kotlin
- var | val 变量 [: 类型] = 初始值
- val 类型的变量不能被赋值超过1次。
字符串初始化
- C/C++把字符串字面量当做指针,char *s = “hello”其实是把"hello"字符串的地址给变量s. "hello"一般存放在全局数据段或只读段。编译器需要计算出地址,当然这里没有字符串拷贝动作。
- C++ string对象初始化将发生对象构造,可能涉及到内存空间分配和拷贝。动态内存分配只发生在堆对象,栈对象内存分配栈自动完成。
- Java String对象永远是引用堆内存。
特定语句中初始化
- C++ 初始化器简化了局部代码变量初始化代码
- Modern C++允许在if语句中包括一个初始化器,变量只能在if/elseif/else body内使用。
- 如上,switch语句也可包含初始化。
- C++20增加了for循环范围初始化器
- for (std::array arr{1, 2, 3}; int i : arr) { std::cout << i << std::endl; }
- 结构化绑定,允许将一个数组或结构体或pair的元素依次赋值给一些变量
- std::array arr{1, 2};
- auto [i, j]{arr}; // i == 1, j == 2
多变量初始化
- Python和Go语言提供多变量统一在赋值表达式右侧初始化,例如:
Go语言:x, y := 1, 2
变量初始化省略缺省类型?
- 对于支持缺省类型的编程语言,初始化可以用缺省类型,编译器可以根据数值推断默认类型。但如果是声明,缺省类型就不能缺少。
- 例如Kotlin 就遵循此规则。
赋值运算符
赋值是编程语言基本操作,即便如此,赋值运算符也并不唯一。大部分编程语言"="是赋值,"=="是相等。一个常见的疑问是,赋值运算符"="和数学的相等是一个符号,这会产生误解吗?
=和==
在数学或者计算机科学中,判断相等相比于赋值,个数少的可怜。按照编码理论,出现次数越多的符号用最少的字符编码更有利。用"="当做赋值,"=="相等也是有道理的。
- C/C++可能误用赋值为逻辑判等,但编译器可能不会理会,因为赋值的结果为整型依然被当做合法的逻辑值。这很灵活,字符串结尾判断代码相当简洁,但可能被误用。
- Java作为一门安全设计的语言,可能的误用,编译器会直接报警。
不同的赋值运算符
- 大部分主流语言支持”=”作为赋值,也支持复合赋值运算符(如+=, -=, *=, /=, %=)
- C/ObjC/C++/Python/C#/Java/JavaScript/Ruby/Swift/仓颉/Go/Rust/VB.NET/PHP/Kotlin 等均支持。
- Shell/Batch批处理/VB6 支持"="赋值,但不支持复合赋值运算符。
- VB 赋值语句开头可以额外增加 Let 显式指示。
- C#复合赋值与C语言有差异,它是调用相应方法实现:a += b相当于a = a.Add(b).
- PHP还支持 ".=" 实现字符串拼接。
- 另外一种赋值运算符:=,最早起源于Algol语言,Go语言也使用这种赋值方式做函数内变量无需声明快速赋值。Pascal和Ada都采用:=作为赋值,把=当成相等比较运算符,这与上面"=="作为相等判断不同。
赋值运算符前后的空格
- 编译型语言一般可以忽略空白字符,会忽略赋值运算符左右的空格。
- Shell语言用于命令控制,赋值左右不能随便加空格。
连续赋值
- C语言支持形如 i = j = k = 0, 简化了多个变量初始化。主流编程语言均支持,如C/ObjC/C++/Java/C#/Python/Ruby等。
- Pascal 不支持连续赋值。
赋值和相等比较的误用
- C/ObjC/C++
if (x = 1) 可能不是预期,但GCC/G++默认不报警,打开-Wall后提示:
"建议在用作真值的赋值语句前后加上括号 [-Wparentheses]"
一些古老的复合赋值运算符
- C语言早期,曾出现过 =+ 代表当今 += 加法复合赋值运算符(=-也类似)。C标准已经废弃了这种做法。
若文章对您有帮助,欢迎关注 程序员小迷 。助您在编程路上越走越好!
微风不燥,阳光正好,你就像风一样经过这里,愿你停留的片刻温暖舒心。
我是 程序员小迷 (致力于C、C++、C#、Android、iOS、Java、Kotlin、Objective-C、Swift、Shell、JavaScript、TypeScript、Python等编程技术的技巧经验分享),若作品对您有帮助,请关注、分享、点赞、收藏、在看、喜欢,您的支持是我们为您提供帮助的最大动力。