C语言--实现AES时的全局变量与const用法

有如下代码:

 1 #include <sdtio.h>
 2 int A = 3;
 3 const int B = 4;
 4
 5 main()
 6 {
 7     int state[2*A];  // error
 8
 9     int tst[B];  //error
10 }

以上两个数组声明语句都是错误的,因为数组长度要求是常数,而A、B都是变量,所以是错误的。A、B是变量,只不过作用域为全局,const型的不能修改而已。

关于const的详细解释,请看http://www.jb51.net/article/70831.htm,这里面解释的很详细。一下内容均摘自这篇文章

关键字const用来定义常量,如果一个变量被const修饰,那么它的值就不能再被改变,我想一定有人有这样的疑问,C语言中不是有#define吗,干嘛还要用const呢,我想事物的存在一定有它自己的道理,所以说const的存在一定有它的合理性,与预编译指令相比,const修饰符有以下的优点

1、预编译指令只是对值进行简单的替换,不能进行类型检查

2、可以保护被修饰的东西,防止意外修改,增强程序的健壮性

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

下面我们从几个方面来说一下const的用法:

一、修饰局部变量

const int n=5;
int const
n=5;
这两种写法是一样的,都是表示变量n的值不能被改变了,需要注意的是,用const修饰变量时,一定要给变脸初始化,否则之后就不能再进行赋值了。

接下来看看const用于修饰常量静态字符串,例如:

const char*
str="fdsafdsa";
如果没有const的修饰,我们可能会在后面有意无意的写str[4]=‘x‘这样的语句,这样会导致对只读内存区域的赋值,然后程序会立刻异常终止。有了const,这个错误就能在程序被编译的时候就立即检查出来,这就是const的好处。让逻辑错误在编译期被发现。

二、常量指针与指针常量

常量指针是指针指向的内容是常量,可以有一下两种定义方式。

const int * n;
int const * n;
需要注意的是一下两点:

1、常量指针说的是不能通过这个指针改变变量的值,但是还是可以通过其他的引用来改变变量的值的。

int a=5;
const int*
n=&a;
a=6;
2、常量指针指向的值不能改变,但是这并不是意味着指针本身不能改变,常量指针可以指向其他的地址。

int a=5;
int b=6;
const int*
n=&a;
n=&b;
指针常量是指指针本身是个常量,不能在指向其他的地址,写法如下:

int *const n;
需要注意的是,指针常量指向的地址不能改变,但是地址中保存的数值是可以改变的,可以通过其他指向改地址的指针来修改。

int a=5;
int *p=&a;
int* const
n=&a;
*p=8;
区分常量指针和指针常量的关键就在于星号的位置,我们以星号为分界线,如果const在星号的左边,则为常量指针,如果const在星号的右边则为指针常量。如果我们将星号读作‘指针‘,将const读作‘常量‘的话,内容正好符合。int
const * n;是常量指针,int *const n;是指针常量。

指向常量的常指针

是以上两种的结合,指针指向的位置不能改变并且也不能通过这个指针改变变量的值,但是依然可以通过其他的普通指针改变变量的值。

const int* const p;
三、修饰函数的参数

根据常量指针与指针常量,const修饰函数的参数也是分为三种情况

1、防止修改指针指向的内容

void StringCopy(char *strDestination, const char *strSource);
其中 strSource
是输入参数,strDestination 是输出参数。给 strSource 加上 const 修饰后,如果函数体内的语句试图改动 strSource
的内容,编译器将指出错误。

2、防止修改指针指向的地址

void swap ( int * const p1 , int * const p2 )
指针p1和指针p2指向的地址都不能修改。

3、以上两种的结合。

四、修饰函数的返回值

如果给以“指针传递”方式的函数返回值加 const 修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。

例如函数

const char * GetString(void);
如下语句将出现编译错误:

char *str = GetString();
正确的用法是

const char *str = GetString();
五、修饰全局变量

全局变量的作用域是整个文件,我们应该尽量避免使用全局变量,以为一旦有一个函数改变了全局变量的值,它也会影响到其他引用这个变量的函数,导致除了bug后很难发现,如果一定要用全局变量,我们应该尽量的使用const修饰符进行修饰,这样方式不必要的以为修改,使用的方法与局部变量是相同的。

时间: 2024-11-10 15:42:33

C语言--实现AES时的全局变量与const用法的相关文章

C语言的AES加密

C语言的AES加密 稍微封装了几个函数 方便使用 #if 1 #include <stdio.h> #include <stdlib.h> #include <string.h> /*aes_small.c*/ //辅助矩阵 /*s盒矩阵:The AES Substitution Table*/// 256 位的密匙256 位支持长度为32 个字符 static const unsigned char sbox[256]={ //static:内部变量 const:只读

【转】话说C语言const用法

原文:话说C语言const用法 const在C语言中算是一个比较新的描述符,我们称之为常量修饰符,意即其所修饰的对象为常量(immutable). 我们来分情况看语法上它该如何被使用. 1.函数体内修饰局部变量.例:void func(){const int a=0;} 首先,我们先把const这个单词忽略不看,那么a是一个int类型的局部自动变量,我们给它赋予初始值0. 然后再看const. const作为一个类型限定词,和int有相同的地位.const int a;int const a;是

angularjs中directive声明scope对象时修饰符解释和用法

在angular中我们定义directive方法时,可以看到 return { restrict: 'AE', scope: {}, template: '<div></div>', link: function() {} } 除了代码中出现的属性,还有一些其他的属性可供配置,这里不作详述. 今天我们要说的重点是scope字段. 常规用法设置 scope: { name: '=', age: '=', sex: '@', say: '&' } 假设我们的hml代码如下 &l

c语言头文件中定义全局变量的问题

问题是这么开始的: 最近在看一个PHP的扩展源码,编译的时候的遇到一个问题: ld: 1 duplicate symbol for architecture x86_64 仔细看了一下源码,发现在头文件中 出现了全局变量的定义. 简化一下后,可以这么理解: // t1.h #ifndef T1_H #define T1_H int a = 0; #endif //------------------ //t1.c #include "t1.h" #include "t2.h&

C#语言编写代码时常用的三大循环

在我们编写C#语言的过程中,经常会遇到各种需要用循环的时候,但是c#语言中三种常用的循环体(while循环, do while循环,for循环)我们该怎么选择呢? 首先while循环,while循环的书写格式是: while (循环条件)--  (循环条件包括:  值  变量 表达式,  但是必须是bool类型.) { 循环体                      --   (循环体指:   任意功能,任意数量的代码.若只有一句代码时,可以省略花括弧.) } 说明:执行该循环体时,系统会先进

Swift和OC,是编译型语言、解释性语言、运行时语言

首先需要明确的一点是,什么是编译型语言和解释性语言 编译型语言,就是在其执行过程中需要先将其经过编译成机器码来给计算机识别的,其执行效率就会比较高这个是显而易见的,常见比如:C.C++ 而解释型语言,是不用编译这个过程的,只是在执行时通过相应的翻译器(虚拟机)逐行翻译.这样它的跨平台性就会较好,因为可以直接通过编译器编译成需要的平台上的语言,但是有一个问题就是:它每次运行都要讲每行代码逐行解释翻译一遍.常见比如:Python.JS.PHP 由此可见,我们的OC和Swift都是需要先进行编译后才能

C语言宏定义时#(井号)和##(双井号)的用法

C语言中如何使用宏C(和C++)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念).下面对常遇到的宏的使用问题做了简单总结. 关于#和## 在C语言的宏中,#的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量 通过替换后在其左右各加上一个双引号.比如下面代码中的宏: #define WARN_IF(EXP) do{ if (EXP) fprintf(stderr, "Warning: " #EXP &quo

C语言scanf执行时被跳过

运行到第二次开始游戏时,发现GameJudge函数中的scanf无法从键盘中输入数据 这种情况的出现是因为用户在输入结束时都会敲一下回车键才能让程序继续执行, 但是,每次printf会从用户输入缓冲区取出用户输入的内容,这样就会在缓冲区留下回车键, 下一次输入如果是获取一个字符,就会将缓冲区剩余的回车键取出. #include<stdio.h> #include<ctype.h> #include <stdlib.h> #include <time.h> #

R语言安装包时遇到arch&#160;-&#160;i386错误时解决方案

安装DWD包时遇到以下问题(因为在CRAN中不存在此包) 错误如下: * installing *source* package 'DWD' ... ** 成功将'DWD'程序包解包并MD5和检查 ** libs *** arch - i386 Warning: 运行命令'make -f "Makevars" -f "C:/PROGRA~1/R/R-33~1.3/etc/i386/Makeconf" -f "C:/PROGRA~1/R/R-33~1.3/s