C语言拾遗,7新特性之类型申明详解

在项目开发的过程中可能需要开放自己的数据库给别人,但是为了安全不能自己服务器里其他数据库同时开放。那么可以新建一个用户,给该用户开放特定数据库权限

前言

1. 没C++那么恶心的const

 

C语言中的const修饰符用于修饰一个变量是const属性的。被C语言的const修饰的变量具有只读属性,并且不能被修改。

const修饰的变量 !=
常量,
const修饰的变量虽然不能别修改,但是和常量还是有本质的区别的。

在定义const类型的变量的时候,必须进行初始化,当然,在const作为函数的参数的时候,是不需要初始化的。

测试环境:Centos 6.3和Mysql 5.3

PHP7 将类型申明变成了可能,PHP 7 支持的形参类型申明的类型有以下几种

1.1编译器对const变量的优化:

 

编译器通常不为普通const
只读变量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作,使得它的效率也很高。

const
定义的只读变量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的只读变量在程序运行过程中只有一份拷贝(因为它是全局的只读变量,存放在静态区),而#define定义的宏常量在内存中有若干个拷贝。#define宏是在预编译阶段进行替换,而const修饰的只读变量是在编译的时候确定其值。#define宏没有类型,而const修饰的只读变量具有特定的类型。

一、新建用户

  • 整型
  • 浮点型
  • 字符串型
  • 布尔类型

1.2当typedef碰到变量修饰符(const)

 

typedef struct student  {      /*code*/  }Stu_st,*Stu_pst;    1)const Stu_pst stu3;  2)Stu_pst const stu4;

 

对于定义的stu3 和stu4,它们的类型一样吗?答案是一样的。为什么?

在这里我们不能想当然的认为typedef和#define一样,直接进行展开。实际上,因为const修饰的都是变量自身,const对变量进行修饰的时候,不考虑类型,也就是说1)和2)中的typedef类型都被认为是一个类型,而不是被展开。所以上述就相当于是:

const type var
      type const var

也就是说,const修饰的是变量var。

复制代码 代码如下:

函数形参与返回类型声明demo 如下

2. 不多见的volatile

 

volatile 关键字和const
一样是一种类型修饰符,用它修饰的变量表示可以被某些编译器未知的因素更改,比如操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。

 

//登录MYSQL
@>mysql -u root -p
@>密码
//创建用户
mysql> insert into mysql.user(Host,User,Password)
values(“localhost”,”cplusplus”,password(“cplusplus.me”));
//刷新系统权限表
mysql>flush privileges;

/**
 * @author 袁超 <yccphp@163.com>
 */
class Demo{

 /**
 * int $name 则是形参类型声明
 * : int 是返回类型声明
 */
 public function age(int $age) : int
 {
 return $age;
 }

}

3. 结构体

 

这样就创建了一个名为:cplusplus 密码为:cplusplus.me 的用户。

上面我们定义了一个 Demo 类,里面就一个方法,在声明方法时,我们指定了
int $name 要求 函数接收的参数必须是 int
类型的,在参数列表括号后面,我们跟上了 : int
,则是声明了我们这个函数的返回数据类型

3.1 柔性数组

柔性数组又称为0长数组(zero-length
arrays),这是C99加进去的一个特性。可以这样定义一个柔性数组:

struct line {         int length;         char contents[];  };         struct line *thisline = (struct line *) malloc (sizeof (struct line) + this_length);  thisline->length = this_length;

在ISO
C90中,在定义一个类似于柔性数组(在C90标准中还没有柔性数组的概念)的结构体成员的时候,contents[]在定义的时候需要定义成这样:contents[0],其中的0是必须的。

在ISO
C99中,可以直接在结构体中定义一个自由数组成员,自由数组的语法如下:

  • 自由数组成员的长度为0,在定义一个数组的个数的时候,[]中的0不被包括。
  • 自由数组成员是不完全类型,所以对结构体使用sizeof操作符时不会包括自由数组成员的大小
  • 在一个自由数组前必须定义至少一个成员,不能在一个结构体中只定义一个自由数组。
  • 一个结构体如果包含了一个自由数组,或者在一个联合中包含了这种结构体,那么这种结构体或者联合不能成为结构体的成员或者是一个数组的成员。

关于GCC对柔性数组的支持,可以访问这个网站:

 

二、登录测试

$demo = new Demo();

$demo->age(10.23); // 我们传递的是 float 型参数,也能通过检查

4. 在解析表达式时的贪心法则

 

对于这样一个表达式:

a+++b

到底表示的是什么呢?是a+ (++b)还是(a++)
+b?这个就需要考虑C语言在语法分析的时候是以什么方式解析的。

在C语言的编译器进行语法分析的时候,使用的是贪心法则。也就是说在处理表达式的时候,如果当前的字符可以和前一个字符串组成一个有意义的符号,则继续读入下一个字符,直到无法组成一个有意义的字符。

也就说对于上述的表达式,在解析到a+后碰到了+,这个时候,由于a++在C语言中是合法的,那么它继续处理下一个+,由于a+++在C语言中是非法的,那么就不把+作为表达式的一部分,也就说上述的表达式就被解析为:(a++)

  • b。

 

mysql>exit;
@>mysql -u cplusplus -p
@>输入密码
mysql>登录成功

在上面例子中,我们传递的是一个
float类型的参数,但是代码还是能够正常运行起来的

5. 预处理

 

在编译的时候可以使用的一些指令,用于在编译的时候输出一些有用的信息,便于追踪编译过程,以及控制编译。

#line    //改变当前的行数和文件名称,基本语法如下:#line number["filename"]    #error   //编译程序时,如果遇到#error就会产生一个编译错误提示信息,并停止编译。

 

编译器在编译过程预定义了一些宏,用于输出一些编译过程的信息:

_LINE_        //编译器正在编译的行号  _FILE_           //编译器正在变异的文件名  _TIME_           //编译的时间  _STDC_        //判断该文件是不是定义成标准C程序

 

 


参考:《C语言深度剖析》


三、用户授权

这是因为在 php7
中,默认情况下形参类型说明不是完全被限制的,这就意味着我们定义的东西只是一个建议,而不是完全约束

//登录MYSQL
@>mysql -u root -p
@>密码
//首先为用户创建一个数据库(cplusplusDB)
mysql>create database cplusplusDB;
//授权cplusplus用户拥有cplusplusDB数据库的所有权限。
>grant all privileges on cplusplusDB.* to cplusplus@localhost identified by 'cplusplus.me';
//刷新系统权限表
mysql>flush privileges;
mysql>其它操作

当然,我们可以完全限制,我们通过设置来实现

四、部分授权

declare(strict_type=1);
mysql>grant select,update on cplusplusDB.* to cplusplus@localhost identified by 'cplusplus.me';
//刷新系统权限表。
mysql>flush privileges;

这个时候,我们运行上面的代码,则会得到一个 Uncaught Type Error

发表评论