变量和不同的赋值方式(四)

在 makefile 中是支持程序设计语言中变量的概念的,makefile 中的变量只代表文本数据(字符串)。那么在 makefile 中的变量名的规则又有哪些呢?a> 变量名可以包含字符、数字以及下划线;b> 不能包含 ":" , "#" , "=" 或 " ";c> 变量名大小写敏感。下来我们来看看变量的定义和使用,如下

下来我们以代码为例来进行分析说明

CC := gcc
TARGET := hello.out

$(TARGET) : func.o main.o
    $(CC) -o $(TARGET) func.o main.o

func.o : func.c 
    $(CC) -o func.o -c func.c

main.o : main.c
    $(CC) -o main.o -c main.c

.PHONY : rebuild clean all

rebuild : clean all

all : $(TARGET)
    
clean : 
    rm *.o $(TARGET)

我们来看看编译结果是否和之前一样

效果和之前是一样的,那么我们为何这样定义变量呢?在一些大型的工程项目中,我们可能要编译好几个版本,因此定义不同的 TARGET 便会编译出不同的版本。而且这种方法还有个好处就是编译器可以由我们自定义选择,比如我们将上面的 gcc 编译器换成 g++,则只需将 CC := gcc 换成 CC := g++,下来我们来看看编译效果

我们看到编译器已经换为 g++ 了。下来我们来讲讲 makefile 中变量的赋值方式,分为四种:a> 简单赋值(:=);b> 递归赋值(=);c> 条件赋值(?=);d> 追加赋值(+=)。那么不同的赋值方式其意义是不同的!下来我们来对这四种赋值方式进行一一的解释说明

a> 简单赋值(:=):程序设计语言中的通用的赋值方式,只针对当前语句的变量是有效的。其用法如下

b> 递归赋值(=):赋值操作可能影响多个其他变量,所有与目标变量相关的其他变量都将受到影响。其用法如下

c> 条件赋值(?=):如果变量未定义,使用赋值符号中的值定义变量;如果变量已经定义,则赋值无效。其用法如下

d> 追加赋值(+=):原变量值之后加上一个新值,原变量值与新值之间由空格隔开。其用法如下

下来我们还是以代码为例来进行说明

# ex1 (:=)
x := foo
y := $(x)b
x := new

.PHONY : test

test :
    @echo "# ex1 (:=)"
    @echo "x => $(x)"
    @echo "y => $(y)"

经过简单赋值后,x 就为 new 了,而 y 则应该为 foob。我们来看看编译效果

我们看到结果和我们所分析的是一样的。下来我们来看看递归赋值

# ex2 (=)
x = foo
y = $(x)b
x = new

.PHONY : test

test :
    @echo "# ex2 (=)"
    @echo "x => $(x)"
    @echo "y => $(y)"

我们分析下,因为递归赋值是与目标相关的其他变量都会受到影响,那么 x 最后应该为 new,y 就应该为 newb。我们来看看编译结果

为了更加形象对递归赋值进行说明,我们编写代码如下

a = $(b)
b = $(c)
c = hello-makefile

.PHONY : test

test :
    @echo "# ex2 (=)"
    @echo "x => $(x)"
    @echo "y => $(y)"
    @echo "a => $(a)"
    @echo "b => $(b)"
    @echo "c => $(c)"

我们定义 a 依赖于 b,而 b 依赖于 c。此时 c 为 hello-makefile,那么依赖于它的 b 也就变为 hello-makefile 了,此时依赖于 b 的 a 也就变为 hello-makefile 了。x 和 y 此时没定义,看看编译会报错吗?

编译是通过的,证明在 makefile 中是支持这样的写法的,x 和 y 没定义,自然也就为空了。那么 a,b,c 和我们所分析的是一样的。所以在 makefile 中我们一般是很少直接用递归赋值的,因为有可能会意想不到地改变依赖于它的目标。下来我们来看看条件赋值

# ex3 (?=)
x := foo
y := $(x)b
x ?= new

.PHONY : test

test :
    @echo "# ex3 (?=)"
    @echo "x => $(x)"
    @echo "y => $(y)"

我们在最后对 x ?= new,意思是如果前面没定义的话,此时它便为 new。所以 x 最后应该为 foo,y 就应该为 foob。我们来看看编译结果

结果确实是这样的,一般我们会在新定义变量时采用这样的写法,以防止改变之前定义时的语义。最后看看追加赋值

# ex4 (+=)
x := foo
y := $(x)b
x += new

.PHONY : test

test :
    @echo "# ex4 (+=)"
    @echo "x => $(x)"
    @echo "y => $(y)"

根据追加赋值的定义,它是直接在后面加上,但是有一个空格。所以 x 最后应该为 foo new,y 就应该为 foob。我们来看看编译结果

我们看懂啊效果确实是这样的,通过对四种赋值方式的学习,我们发现简单赋值是跟 C 语言中是一样的。追加赋值和 C++ 语言中的语义也是一样的,一般在大型项目中是不会采用递归赋值这种写法的。

欢迎大家一起来学习 makefile,可以加我QQ:243343083。

原文地址:http://blog.51cto.com/12810168/2128270

时间: 2024-07-30 23:51:00

变量和不同的赋值方式(四)的相关文章

变量赋值方式有哪几种?

变量赋值方式一般有以下三种方式: 1)直接赋值 2)变量间赋值 3)引用赋值

PL/SQL基本结构---变量赋值方式

*****************************************   变量赋值方式 ***************************************** oracle中变量赋值方式是值拷贝而非引用         declare         v_number1 number:=100;         v_number2 number;     begin         v_number2:=v_number1;         v_number1:=200

ES6学习笔记二 新的声明方式和变量的解构赋值!

新的声明方式 在ES5的时候,我们只有一个声明方式,var!但是在es6中,声明进行了扩展,我们加上ES5的var的申明方式,我们有了三种声明方式: var:它是variable的简写,可以理解成变量的意思 let:它在英文中是让的意思,也可以理解成一种申明方式 const:它在英文中是常量的意思,在ES6中用来声明常量,常量可以理解成不变的量=>这里的不变不是值得不变,是内存地址的指针不变!!! var 声明: var在ES中是用来升级成全局变量的,我们可以做一个简单实例,声明一个变量,用co

oracle 存储过程 变量的声明和赋值的3种方式

oracle 存储过程 变量的声明和赋值的3种方式 CreationTime--2018年8月31日16点00分 Author:Marydon 1.声明变量的3种方式 按照数据类型的声明方式进行区分 方式一:直接声明数据类型 格式:变量名 数据类型(大小) V_START_DATE VARCHAR2(19); v_num number; 说明: 设置为字符串类型时,需要指定大小,否则报错: 变量的声明必须在"begin"关键字之前进行. --错误用法 BEGIN v_sql varch

make--伪目标 、不同的赋值方式、变量

一.伪目标的引入 a.默认情况下1.make认为目标对应一个文件2.make比较目标文件和依赖文件的新旧关系,决定是否执行命令3.make以文件处理作为第一优先级示例 hello.out all : func.o main.o gcc -o hello.out func.o main.o func.o : func.c gcc -o func.o -c func.c main.o : main.c gcc -o main.o -c main.c clean : rm *.o hello.out

pl sql 变量的声明和赋值

一:pl sql 程序的组成 DECLARE ……声明部分 BEGIN ……程序执行部分 EXCEPTION ……异常处理 END;……结束程序 二:定义变量 DECLARE 变量的名称name 数据类型type: 变量的赋值方法 1.变量的名称name 数据类型type := 给变量赋初始值 2.在内容部分  select  列名    into  变量名: 三:命名规则 1.首字母必须是英文字母,其后可以是字母,数字,$ ,#,和_下划线 2.变量名长度不超过30个字符 3.变量名中不能有空

3. 变量的解构赋值

目录 一. 数组的解构赋值 二. 对象的解构赋值 三. 字符串的解构赋值 四. 布尔和数值的解构赋值 五. 函数的解构赋值 六. 用途 总结 一. 数组的解构赋值 ES6允许按照一定的模式,从数组和对象中提取值,对变量进行赋值,这被称为解构 模式匹配:本质上,这种写法属于模式匹配,只要等号两边的模式相同,左边的变量就会被赋予相应的值 如果解构不成功(即左边的值在右边找不到对应的),则返回undefined 如果等号右边的不是数组(或者说不是可遍历的解构),那么将会报错 默认值,解析赋值允许执行默

ES6学习笔记(let、const、变量的解构赋值、字符串扩展)

一.let命令 1.let命令所在的代码块内有效,var声明的在全局范围内都有效 2.for循环的计数器,就很合适使用let命令 3.let声明的内部变量i和外部变量i是分离的 4.var命令会发生"变量提升"现象,即变量可以在声明之前使用,值为undefined   let命令不会发生"变量提升"现象,它所声明的变量一定要在声明后使用,否则报错 5.let不允许在相同作用域内,重复声明同一个变量 6.let会导致暂时性死区,在代码块内,使用let命令声明变量之前,

[学习笔记]02.变量的解构赋值

一:数组的解构赋值  ES6.0规定按照一定的模式,从数组到对象中提取值,对变量进行赋值,这被称为解构. 以前的时候赋值是这样的形式: var a = 1; var b = 2; var c = 3; 现在是: var [a, b, c] = [1, 2, 3]; 从上面可以看出来可以从数组中提取值,按照对应位置,对变量赋值. 本质上,这种写法属于 " 模式匹配 " ,只要等号两边的模式相同,左边的变量就会被赋予对应的值. let [foo, [[bar], baz]] = [1, [