C语言学习第九天-重要知识点补充

本文详细介绍了C语言中typedef的用法及其与#define的区别,解释了如何使用const定义常量及与指针配合使用的技巧。此外,还介绍了如何生成随机数以及控制随机数的范围。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

typedef的用法

C语言允许为一个数据类型起一个新的别名,就像给人起“绰号”一样。

起别名的目的不是为了提高程序运行效率,而是为了编码方便。

例如有一个结构体的名字是stu,要想定义一个结构体变量就得这样写:

struct stu stu1;

struct看起来就是多余的,但不写又会报错。如果为struct stu起一个别名STU,书写起来就简单了:STU stu1;

这种写法更加简练,意义也非常明确,不管是在标准头文件中还是以后的编程实践中,都会大量使用这种别名。

使用关键字typedef可以为类型起一个新的别名。typedef的用法一般为:

typedef oldName newName;

需要强调的是,typedef 是赋予现有类型一个新的名字,而不是创建新的类型。为了“见名知意”,请尽量使用含义明确的标识符,并且尽量大写。

typedef和#define的区别

typedef在表现上有时候类似于#define,但它和宏替换之间存在一个关键性的区别。正确思考这个问题的方法就是把typedef看成一种彻底的“封装”类型,声明之后不能再往里面增加新的东西。

1. 可以使用其他类型说明符对宏类型名进行扩展,但对typedef所定义的类型名却不能这样做。

2. 在连续定义几个变量的时候,typedef能够保证定义的所有变量均为同一类型,而#define则无法保证。

const的用法

可以使用const关键字对变量加以限定,使得变量的值不能被改变,在整个作用域中都保持固定。此时任何对此变量赋值的行为都将引发错误。const变量又被称为常量。

创建常量的格式通常为:

const type name = value; 

const和type都是用来修饰变量的,它们的位置可以互换,也就是将type放在const前面:

type const name = value; 

另外建议将常量名的首字母大写,以提醒程序员这是个常量。

由于常量一旦被创建后其值就不能再改变,所以常量必须在定义的同时赋值(初始化),后面的任何赋值都将引发错误。一如既往,初始化常量可以使用任意形式的表达式。

const和指针

const也可以和指针变量一起使用,这样可以限制指针变量本身,也可以限制指针指向的数据。

const和指针一起使用会有几种不同的顺序,如下所示:

const int *p1; 

int const *p2;

int * const p3;

在最后一种情况下,指针是只读的,也就是p3本身的值不能被修改;在前面两种情况下,指针所指向的数据是只读的,也就是p1、p2本身的值可以修改(指向不同的数据),但它们指向的数据不能被修改。

当然,指针本身和它指向的数据都有可能是只读的,下面的两种写法能够做到这一点:

const int * const p4;  

int const * const p5; 

const离变量名近就是用来修饰指针变量的,离变量名远就是用来修饰指针指向的数据,如果近的和远的都有,那么就同时修饰指针变量以及它指向的数据。

const和函数形参

在C语言中,单独定义const变量没有明显的优势,完全可以使用#define命令代替。const通常用在函数形参中,如果形参是一个指针,为了防止在函数内部修改指针指向的数据,就可以用const来限制。

const和非const类型转换

当一个指针变量str1被const限制时,并且类似const char *str1这种形式,说明指针指向的数据不能被修改;如果将str1赋值给另外一个未被const修饰的指针变量str2,就有可能发生危险。因为通过str1不能修改数据,而赋值后通过str2能够修改数据了,意义发生了转变,所以编译器不提倡这种行为,会给出错误或警告。

也就是说,const char*和char*是不同的类型,不能将const char*类型的数据赋值给char*类型的变量。但反过来是可以的,编译器允许将char*类型的数据赋值给const char*类型的变量。

这种限制很容易理解,char*指向的数据有读取和写入权限,而const char*指向的数据只有读取权限,降低数据的权限不会带来任何问题,但提升数据的权限就有可能发生危险。

C语言标准库中很多函数的参数都被 const 限制了,但我们在以前的编码过程中并没有注意这个问题,经常将非 const 类型的数据传递给 const 类型的形参,这样做从未引发任何副作用,原因就是上面讲到的,将非 const 类型转换为 const 类型是允许的。

随机数生成

在C语言中,我们一般使用<stdlib.h>头文件中的rand()函数来生成随机数,它的用法为:

int rand(void); 

void表示不需要传递参数。

rand()会随机生成一个位于0~RAND_MAX之间的整数。

RAND_MAX是<stdlib.h>头文件中的一个宏,它用来指明rand()所能返回的随机数的最大值。C语言标准并没有规定RAND_MAX的具体数值,只是规定它的值至少为32767。

随机数的本质

实际上,rand()函数产生的随机数是伪随机数,是根据一个数值按照某个公式推算出来的,这个数值我们称之为“种子”。种子和随机数之间的关系是一种正态分布。种子在每次启动计算机时是随机的,但是一旦计算机启动之后它就不再变化了;也就是说,每次启动计算机以后,种子就是定值了,所以根据公式推算出来的结果(也就是生成的随机数)就是固定的。

重新播种

我们可以通过srand()函数来重新“播种”,这样种子就会发生改变。

srand()的用法为:

void srand(unsigned int seed); 

它需要一个unsigned int类型的参数。在实际开发中,我们可以用时间作为参数,只要每次播种的时间不同,那么生成的种子就不同,最终的随机数也就不同。

使用<time.h>头文件中的time()函数即可得到当前的时间(精确到秒),就像下面这样:

srand((unsigned)time(NULL)); 

多次运行程序,会发现每次生成的随机数都不一样了。但是,这些随机数会有逐渐增大或者逐渐减小的趋势,这是因为我们以时间为种子,时间是逐渐增大的,结合上面的正态分布图,很容易推断出随机数也会逐渐增大或者减小。

生成一定范围内的随机数

在实际开发中,我们往往需要一定范围内的随机数,过大或者过小都不符合要求,那么,如何产生一定范围的随机数呢?我们可以利用取模的方法:

int a = rand() % 10; 

产生0~9的随机数,注意10会被整除

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值