1)简单介绍C99
C99( ISO/IEC 9899:1999 - Programming languages -- C)是C语言的官方标准第二版。1999年12月1日,国际标准化组织(ISO)和国际电工委员会(IEC)旗下的C语言标准委员会(ISO/IEC JTC1/SC22/WG14)正式发布了这个标准文件 。(摘抄百度百科C99标准)
2)简单介绍_Bool和_Complex、_Imaginary
_Bool(布尔值类型)
对于学过其他语言(C++,JAVA等)的小伙伴来说布尔值类型肯定是不陌生的,
可是C语言在C99前还是没有布尔值类型的。
C99新增了stdbool.h头文件
stdbool.h定义如下:(摘抄stdbool.h)
<span style="color:#333333">//
// stdbool.h
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// The C Standard Library <stdbool.h> header.
//
#ifndef _STDBOOL
#define _STDBOOL
#define __bool_true_false_are_defined 1
#ifndef __cplusplus
#define bool _Bool
#define false 0
#define true 1
#endif /* __cplusplus */
#endif /* _STDBOOL */
/*
* Copyright (c) 1992-2010 by P.J. Plauger. ALL RIGHTS RESERVED.
* Consult your license regarding permissions and restrictions.
V5.30:0009 */</span>
在stdbool.h中可以看到定义了bool、true、falses三个我们用到的宏
bool _Bool(布尔值类型)
true(真) 1
false(假) 0
PS:_Bool(布尔值类型)占用字节大小为1字节,原则来说1位内存大小就够了(0或1)
PS:C语言没有true,false关键字。
PS:判断真和假,true(真)只要大于1,false(假)0
_Complex(复数类型)
☆1)为什么要添加复数类型?
因为许多科学和工程计算都要用到负数和虚数。
☆2)复数类型和虚数类型都是有所保留的
但是复数和虚数都是有所保留的,因为不是所有程序都会用到复数和虚数,所以复数和虚数都是作为可选择的。
C11标准把整个复数软件包都作为可选项。
☆3)C语言的复数类型和虚数类型
目前C语言定义了三种复数类型:
float _Complex、double _Complex、long double _Complex
目前C语言定义了三种虚数类型:
float _Imaginary、double _Imaginary、long double _Imaginary
如果包含了complex.h则可以使用complex代替_Complex
☆4)复数类型解析
_Complex(复数类型)
复数类型分别定义了两个部分,一个表示实部,一个表示虚部。
举例说明:
float _Complex 那么分别定义了两个float(单精度浮点数类型),一个表示实部,另一个表示虚部。
☆5)_Imaginary(虚数类型)
因为_Complex(复数类型)里面已经包含虚数了,所以跟_Imaginary(虚数类型)存在重叠了,然而因为_Complex(复数类型)和_Imaginary(虚数类型)都不是硬性规定必须实现的,所以部分编译器都只实现了_Complex(复数类型)而没有实现_Imaginary(虚数类型)。
PS:(VS、DEV)没有实现_Imaginary(虚数类型)
3)_Bool(布尔值类型)和_Complex(复数类型)、_Imaginary(虚数类型)的简单使用
由于_Bool(布尔值类型)比较简单易懂所以就先从TA开始吧!
☆1)_Bool(布尔值类型)
占用内存大小:
printf("type _Bool size:%u\n", sizeof(_Bool)); //1
_Bool(布尔值类型)占1字节内存大小
赋值操作:
<span style="color:#333333">#include <stdio.h>
#include <limits.h>
int main(void)
{
long int llTestTrueValue = LONG_MAX; //long max
long int llTestFalseValue = LONG_MIN; //long min
_Bool bTrue = 1; //true
_Bool bFlase = 0; //false
_Bool bTestTrue = llTestTrueValue; //test true
_Bool bTestFalse = llTestFalseValue; //test false
printf("-----------------test value-----------------\n");
printf("test true value:%ld\n", llTestTrueValue); //2147483647
printf("test false value:%ld\n", llTestFalseValue); //-2147483648
printf("--------------_Bool test value--------------\n");
printf("_Bool test true value:%d\n", bTestTrue); //1
printf("_Bool test false value:%d\n", bTestFalse); //1
printf("--------------------_Bool-------------------\n");
printf("_Bool true value:%d\n", bTrue); //1
printf("_Bool false value:%d\n", bFlase); //0
return 0;
}</span>
从上面可以看到任何数字进行对_Bool(布尔值类型)的变量进行赋值的时候都会先进行转换一下,赋值一个大于0和小于0的数字都会被转换成1,只有赋值0才会是0。所以可以总结得到将一个非0的数赋值给_Bool(布尔值类型)的变量都会被转换成1。
使用:
使用_Bool(布尔值类型)变量进行判断
<span style="color:#333333">#include <stdio.h>
#include <stdbool.h>
int main(void)
{
bool bTrue = true; //true
bool bFlase = false; //false
if(bTrue)
printf("true\n"); //true
else
printf("false\n"); //false
return 0;
}</span>
PS:此处包含了stdbool.h,可以让读者了解stdbool.h的使用
之前介绍了stdbool.h中定了三个我们用到的宏,分别是bool,true,false
bool _Bool(布尔值类型)
true 1
false 0
所以上面赋值true,就等于直接赋值了1给布尔值类型的变量,false就等于赋值了0给布尔值类型的变量。
判断_Bool(布尔值类型)的变量,因为只有0为false,所以任何非0值都为true,因此输出true。
☆2)_Complex(复数类型)和_Imaginary(虚数类型)
占用内存大小:(此处使用的编译器为DEV)
<span style="color:#333333">#include <stdio.h>
int main(void)
{
printf("float _Complex size:%u\n", sizeof(float _Complex)); //8
printf("double _Complex size:%u\n", sizeof(double _Complex)); //16
printf("long double _Complex size:%u\n", sizeof(long double _Complex)); //32
return 0;
}</span>
三种复数类型分别占用内存大小:
float _Complex 8字节
double _Complex 16字节
long double _Complex 32字节
PS:拿float _Complex来说,一个float占用4字节,所以一个float _Complex占用了两个float,所以float _Complex分别定义了一个float的实部和虚部。
赋值:
实数部分赋值:
float _Complex fCex = 1.0f; //赋值实数部分
虚数部分赋值:
float _Complex fCex = 1.0if; //赋值虚数部分
PS:两个赋值之间的差别就是实数部分赋值是1.0f,虚数部分赋值是1.0if,i表示虚数(按道理来说就是imaginary的缩写第一个字母)
然后你们会问那样怎么实数虚数一起赋值吖?
float _Complex fCex = 1.0f + 1.0if; //实数 虚数 一起赋值
= 1.0f + 1.0if; //实数 虚数 一起赋值
因为i代表虚数所以后面的1.0if就是虚数部分,前面的1.0f就是实数部分了
计算:
float _Complex fCex = 0.0f;
fCex = fCex + 2.0f * 5.0f + 2.0if * 5.0f;
2.0f * 5.0f为实部,2.0if * 5.0f为虚部
看完上面是不是觉得会很容易漏写了i
为此我们可以自己定义一个i或者使用complex.h
定义一个宏表示虚数i:
<span style="color:#333333">#define CUSTOM_IMAGINARY 1.0if //自定义虚数为1.0</span>
使用这个定义的i
float _Complex fCex = 1.0f + 1.0f * CUSTOM_IMAGINARY;
complex.h
在complex.h中已经为我们定义了一个宏I,定义如下:
<span style="color:#333333">#define I _Complex_I
#define _Complex_I (0.0F + 1.0iF)</span>
而且还定义了一个complex的宏,代替_Complex,定义如下:
<span style="color:#333333">#ifndef __cplusplus
#define complex _Complex
#endif</span>
PS:如果已经定义了complex相关的结构体关键字,枚举类型,或者typedef定义的自定义名称,再包含complex.h就会出现的错误,所以使用complex.h之前要注意项目是否已经定义了complex的类型!!!
如何获取_Complex的实部和虚部?
在complex.h已经为我们提供了获取实部和虚部的函数:
实部的获取:
float _Complex crealf(float _Complex) 获取float _Complex的实部
double_Complex creal(double _Complex) 获取double _Complex的实部
long double _Complex creall(long double _Complex) 获取long double _Complex的实部
虚部的获取:
float _Complex cimagf(float _Complex) 获取float _Complex的虚部
double_Complex cimag(double _Complex) 获取double _Complex的虚部
long double _Complex cimagl(long double _Complex) 获取long double _Complex的虚部
PS:当然了complex.h中还提供了许多函数,比如csqrtf(计算平方根),ccosf(复数的余弦值)...等等
为什么没有讲_Imaginary?
因为复数_Complex中已经包含了_Imaginary了,而且很少编译器提供了这个_Imaginary(虚数类型)关键字,所以就没有讲啦~
4)关于_Bool(布尔值类型)和_Complex(复数类型)、_Imaginary(虚数类型)的命名
因为标委会考虑到,如果使用新的关键字,会导致以该关键字作为标识符的现有代码全部失效,比如定义了一个struct complex{...};的结构体,那样会让complex成为关键字会导致之前的这些代码出现语法错误。但是使用struct _Complex的人很少,特别是标准使用首字母是下划线的标识符作为预留字以后。因此委员会选定_Complex作为关键字,在不考虑名称冲突的情况下可以选择complex作为关键字,通过包含complex.h里面定义了complex的宏代替_Complex。
所以_Bool和_Complex、_Imaginary关键字名称不同之前的关键字所字母为下划线开头就是为了避免在C99之前已经定义了complex的发生冲突。