TCPL(The C Programming Language)读书笔记 第二章 类型、运算符与表达式

2.1 变量名

变量名由字母和数字组成,但第一个字符必须是字母。下划线“_”被看作是字母,通常用于命名较长的变量名。由于例程的名字通常以下划线开头,因此变量名不要以下划线开始。在传统的C语言中,变量名使用小写字母,符号常量全部使用大写字母。

类似于ifelseintfloat等关键字是保留给语言本身使用的,不能用作变量名,所有关键字中的字符都必须小写。

2.2 数据类型及长度

    C语言中只提供了这几种基本数据类型:char,int,float,double。此外,还可以在这些基本数据类型的前面加一些限定符。shortlong用于限定整型:

short int sh;

long int counter;

上述声明中,关键字int可以省略,通常人们也习惯这样做。

int通常代表特定机器中整数的自然长度。short类型通常为16位,long类型通常为32位,int类型可为16位或32位。注意,无论什么硬件条件,shortint类型至少为16位,long至少32位,且short不得长于int型,int型不得长于long型。

类型限定符signedunsigned可用于限定char类型或任何整型。unsigned类型的数总是正值或0,并遵守算术模2n定律,其中n是该类型占用的位数。

long double类型表示高精度的浮点数。

有关这些类型长度定义的符号常量以及其他与机器和编译器有关的属性可以在标准头文件<limits.h><float.h>中找到。

 

程序练习2-3知,二进制、八进制、十六进制转换为十进制的简单方法,编程很方便。假设十六进制数(0f93)16=((f*16)+9)*16+3=(3987)10

进行位运算时,要注意:第一位时指地位的第一位,二进制数的右边的第一位。

2.3 常量

类似于1234整数常量属于int型,long类型的常量以字母lL结尾,如果一个整数太大以至于无法用int类型表示时,也将被当做long类型处理。无符号常量以字母u或者U结尾。后缀ulUL表明时unsigned long型。

浮点数常量中包含一个小数点(如123.4)或一个指数(如le-2),也可以两者都有。没有后缀的浮点数常量为double型。后缀为fF表示float类型,而后缀lL则表示long double型。

整型数除了用十进制表示外,还可以用八进制或十六进制表示。带前缀0的整型常量表示它为八进制;带前缀0x0X的整型常量表示它为十六进制。

一个字符常量是一个整数,书写时将一个字符括在单引号中,字符在机器字符集中的数值就是字符常量的值。如在ASCII字符集中,0的值为48,它与数值0没有关系。

ANSI C语言中全部转义字符表

/a

响铃符

//

反斜杠

/b

回退符

/?

问号

/f

换页符

/’

单引号

/n

换行符

/”

双引号

/r

回车符

/ooo

八进制数

/t

横向制表符

/xhh

十六进制数

/v

纵向制表符

 

 

    字符常量’/0’表示值为0的字符,也就是空字符(null。我们通常用’/0’的形式代替0,以强调某些表达式的字符属性,但其数字值为0

字符串常量也叫字符串字面值,是用双引号括起来的0或多个字符组成的字符序列。从技术角度看,字符串常量就是字符数组,且使用空字符’/0’作为串结尾,因此,存储字符串的物理单元数比括在双引号中的字符数多一个。标准库函数strlen(s)可以返回s的长度,但长度不包括末尾的空字符。

字符和字符串之间的区别’x’”x”是不同的,前者是一个整数,后者是一个包含一个字符以及一个结束符’/0’的字符数组。

枚举常量时另外一种类型的常量,枚举是一个常量整型值的列表。在没有显示说明的情况下,enum类型中第一个枚举名的值为0,第二个为1,依次类推。如果只指定了部分枚举名的值,那么未指定的枚举名的值将依着最后一个指定值向后递增。如:

enum escapes {BELL=’/a’,BACKSPACE=’/b’,TAB=’/t’};

enum months{JAN=1,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC};

/*FEB=2MAR=3,依次类推*/

不同枚举中的名字必须互不相同,同一枚举中不同的名字可以具有相同的值。

枚举与#define语句相比,优势在于常量值可以自动生成。

2.4 声明

所有变量必须先声明后使用。

任何变量的声明都可以使用const限定符限定。该限定符指定变量的值不能被修改。对数组而言,const限定符指定数组所有元素的值都不能被修改。

const也可以配合数组参数使用,它表示函数不能修改数组元素的值:

int strlen(const char[]);

2.5 算术运算符

需要注意,一是取模运算符%不能应用于floatdouble型;二是运算符的优先级。

2.6 关系运算符与逻辑运算符

关系运算符:>,<,>=,<=

需要注意,逻辑运算符&&||有一些较为特殊的属性,由&&||连接的表达式按从左到右的顺序进行求值,且在知道结果值为真或假后立即停止计算(&&优先级比||高)。

在关系表达式或逻辑表达式中,如果关系为真则表达式结果值为数值1;反之为0

2.7 类型转换

当一个运算的几个操作数类型不同时,就需要通过一些规则把它们转换为某种共同的类型。一般来说,自动转换是指把“比较窄的”操作数转换为“比较宽的”操作数,并且不丢失信息的转换。如:f+i时,将i自动转换为浮点型f型。

注意,表达式中float型不会自动转换为double型。

强制转换: (类型)表达式;

2.8 自增运算符与自减运算符

    ++--,既可以用作前缀运算符,也可以用作后缀运算符。在这两种情况下,其效果都是将变量n的值加1,但是++n先将n的值递增1,然后再使用n的值;而n++先使用n的值再将n的值递增1

2.9 按位运算符

6种:&,|,^,<<,>>,~

按位与运算符&经常用于屏蔽某些二进制位;按位或运算符|常用于将某些二进制位置为1;按位与或运算符^当两个操作数的对应位不同时该位置为1,否则置为0.

2.10 赋值运算符与表达式

2.11 条件表达式

expr1 ? expr2 : expr3

首先计算expr1,如果值不等于0(为真),则计算expr2的值,并以该值作为条件表达之的值,否则计算expr3的值,并以该值作为条件表达之的值。

2.12 运算符优先级与求值次序

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很抱歉,我不是一个可以运行代码的程序,无法为您提供完整的源代码和报告。但我可以简要介绍如何在NS3中编写纺锤型网络,并使用不同的拥塞控制算法进行性能测试。 1. 编写纺锤型网络 在NS3中,我们可以使用TopologyHelper类来构建网络拓扑。对于八个节点的纺锤型网络,可以按照以下方式实现: ``` Ptr<Node> n0 = CreateObject<Node>(); Ptr<Node> n1 = CreateObject<Node>(); Ptr<Node> n2 = CreateObject<Node>(); Ptr<Node> n3 = CreateObject<Node>(); Ptr<Node> n4 = CreateObject<Node>(); Ptr<Node> n5 = CreateObject<Node>(); Ptr<Node> n6 = CreateObject<Node>(); Ptr<Node> n7 = CreateObject<Node>(); // 创建点对节点 PointToPointHelper pointToPoint; pointToPoint.SetDeviceAttribute("DataRate", StringValue("5Mbps")); pointToPoint.SetChannelAttribute("Delay", StringValue("2ms")); // 设置节点之间的连接 NetDeviceContainer devices; devices.Add(pointToPoint.Install(n0, n1)); devices.Add(pointToPoint.Install(n1, n2)); devices.Add(pointToPoint.Install(n2, n3)); devices.Add(pointToPoint.Install(n3, n4)); devices.Add(pointToPoint.Install(n4, n5)); devices.Add(pointToPoint.Install(n5, n6)); devices.Add(pointToPoint.Install(n6, n7)); devices.Add(pointToPoint.Install(n7, n0)); // 安装网络协议栈 InternetStackHelper stack; stack.InstallAll(); ``` 上述代码中,我们创建了八个节点,并使用PointToPointHelper类创建点对点的连接。接下来,我们将八个节点两两相连,构成一个纺锤型网络。最后,我们使用InternetStackHelper类安装网络协议栈。 2. 使用不同的拥塞控制算法 NS3提供了多种拥塞控制算法,例如TCP NewReno、TCP Vegas、TCP Cubic等。我们可以在仿真程序中选择不同的算法来测试其性能。 ``` // 创建Socket和Application uint16_t port = 50000; Address sinkAddress(InetSocketAddress(Ipv4Address::GetAny(), port)); PacketSinkHelper packetSinkHelper("ns3::TcpSocketFactory", sinkAddress); ApplicationContainer sinkApps = packetSinkHelper.Install(nodes.Get(0)); sinkApps.Start(Seconds(0.0)); sinkApps.Stop(Seconds(simulationTime + 0.1)); OnOffHelper onoff("ns3::TcpSocketFactory", sinkAddress); onoff.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]")); onoff.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]")); onoff.SetAttribute("DataRate", DataRateValue(DataRate("5Mbps"))); onoff.SetAttribute("PacketSize", UintegerValue(1000)); // 安装TCP协议 Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(1000)); Config::SetDefault("ns3::TcpSocketBase::MaxWindowSize", UintegerValue(50000)); Config::SetDefault("ns3::TcpL4Protocol::SocketType", StringValue("ns3::TcpNewReno")); ApplicationContainer clientApps = onoff.Install(nodes.Get(1)); clientApps.Start(Seconds(0.0)); clientApps.Stop(Seconds(simulationTime + 0.1)); ``` 上述代码中,我们创建了一个TCP Socket和一个TCP Application,并使用不同的拥塞控制算法来测试网络性能。在这里,我们选择了TCP NewReno算法。使用Config::SetDefault()函数可以设置TCP Socket的一些参数,例如最大窗口大小等。 3. 性能测试和报告 在仿真程序中,我们可以使用Simulator::Run()函数来运行仿真。在仿真结束后,我们可以获取一些性能指标,例如吞吐量、延迟、丢包率等,并根据这些指标来评估不同的拥塞控制算法。 ``` Simulator::Stop(Seconds(simulationTime + 0.1)); Simulator::Run(); // 获取性能指标 uint64_t totalPacketsThrough = DynamicCast<PacketSink>(sinkApps.Get(0))->GetTotalRx(); double throughput = totalPacketsThrough * 8 / (simulationTime * 1000000.0); // Mbps double avgDelay = 0; for (uint32_t i = 0; i < clientApps.GetN(); ++i) { Ptr<OnOffApplication> onoffApp = DynamicCast<OnOffApplication>(clientApps.Get(i)); Time startTime = onoffApp->GetStartTime(); Time stopTime = onoffApp->GetStopTime(); double thisDelay = (stopTime.GetSeconds() - startTime.GetSeconds()) * 1000.0; avgDelay += thisDelay; } avgDelay /= clientApps.GetN(); // ms uint64_t totalPacketsDropped = DynamicCast<PacketSink>(sinkApps.Get(0))->GetLost(); double packetLossRate = totalPacketsDropped * 1.0 / totalPacketsThrough; // 输出性能指标 std::cout << "Throughput: " << throughput << " Mbps" << std::endl; std::cout << "Average Delay: " << avgDelay << " ms" << std::endl; std::cout << "Packet Loss Rate: " << packetLossRate * 100 << "%" << std::endl; ``` 上述代码中,我们获取了网络的吞吐量、平均延迟和丢包率等性能指标,并输出到控制台。 根据上述代码,我们可以编写出完整的仿真程序,并根据不同的拥塞控制算法进行测试。在测试中,我们可以使用如下代码切换不同的拥塞控制算法: ``` Config::SetDefault("ns3::TcpL4Protocol::SocketType", StringValue("ns3::TcpNewReno")); // 使用TCP NewReno算法 Config::SetDefault("ns3::TcpL4Protocol::SocketType", StringValue("ns3::TcpVegas")); // 使用TCP Vegas算法 Config::SetDefault("ns3::TcpL4Protocol::SocketType", StringValue("ns3::TcpCubic")); // 使用TCP Cubic算法 ``` 最终,我们可以根据实验结果,撰写不同拥塞控制算法对网络性能的影响的详细报告。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值