const 的用法

本文详细解析了C/C++中const限定符的使用方法及其含义,包括如何限制变量和指针的可修改性,并探讨了不同类型指针之间的兼容性问题。

 很久就说来写一篇文章,以便于加加分数,但是一直都没有写。
不过,也没有忘记。

今天想跟大家讨论讨论const和volatile.
说起const的话,可能第一个反应应该就是常量吧?
其实把它的理解为常量是不对的。在一个符号前面加一个const
只是表示这个符号不能被赋值.也就是它的值对于这个符号来说
是只读的,但并不能防止其它的方法来改变这个值的值.我想,
const最有用的地方就是把它用来限定形参,这样函数将不会修
改实参指针所指向的数据,但其它的函数却可能可以。
注:若是不对的话,请指正。thanks in advanced.

比如说:int const a=10; //当然您也可以这样子写const int a=10;
             //只是我个人比较喜欢这样子也而且,
             //个人觉得好读一点点。

表示的是a不能做左值。只能做右值。这个时候的a就是不能被改变的。
但是要是您要是加上指针的话,可能就变得有些麻烦了,如:

int    b=20;
int const *p=&b;     //一个指向整型数据的指针。

很多的人在这个地方很不理解,我慢慢的解释一下。

跟上面的int const 一样 ,既然a是不能做为左值的,那么此时的
*p也同样是不能做为左值.即b是不可以通过*p来改变的。(希望这
个地方没有把您给弄晕等一下我会给出例子,看了就会明白了).

既然,*p不可以改变,那么p可不可以改变呢?可以,p是可以改变的
喔。因为我们并没有限定p,而只是限定了它所指向的数值。那么
怎么样子限定p呢?int *const p;    //就可以了。
现在的p就是不能修改的了.

举个例子来说吧:

    int a=3;
    int const b=2;
    int const *p=&b;
    int *const pl=&a;

    a=10;    //这个肯定是对的撒.

    b=20;   //错的.  b不能做为左值.

    p=&a;   //对的。我们并没有限定p,只是限定了p所指向的
        //数据,而这个数据也没有成为左值,当然是可以的了.

    *p=40;  //错的。跟我们刚刚说的一样,*p是不可以做为左值的。
        //修改*p就意味着去修改a,而a已经被p所保护,
        //所以这里会给出错误提示或者是警告.

    pl=&b;  //错的,pl是一个常量指针,指向整型数a。
   

既然都说到这里来了,我就索性把有关的都说了吧。
上面说的左值和右值我就再解释一下吧。
简单的说来就是等式的左边和右边。
eg: a=b;这一个赋值的语句。
a就是左值,b就是右值.
a用的是地址,而且只能是地址,b用的是数值,并且只能是数值.
也就是说,对于一个等式的话,位于左边的,一定是一个地址,
而右边的一定是一个数值了.
我再说一个比较难于理解的吧。就是常常犯错的一点。我想举个例子来说
的话或者更于明白。

void func(char const **pt)
{...}

int main(int argc,char **argv)
{
    ...
    func(argv);  //这里会出现警告或者是错误。
    ...
}

    我在解释这个例子之前,好好的整理了一下我自己的语言,
因为要把这一个问题解释清楚,还真的是不太容易。
解释之前,我先把我们要说的提出来吧,就是“相容”问题。
若是我们将上面的char ** 和char const **改成char * 和char const *
那么,上面的调用却又是没有问题的。不信的话,可以试试。
也就是说,char * 和char const * 是相容的。那为什么char **和char
const ** 却又是不相容的呢?
在ANSI C 里面有这么一句话:
    每个实参都应该具有自己的类型,这样它的值就可以给与它所对应
的形参类型的对象(该对象的类型不能含有限定符).

    要使赋值合法,必须满足以下的条件之一:
    两个操作数都是指向有限定符或无限定符的相容类型的指针,左边指针
指向的类型必须具有右边指针所指向类型的全部限定符。

也就是说,相空的才可以相互赋值,而不相容的就不可以。首先呢?得明白,
参数的传递其实就是类似于赋值的一个过程.正是由于上面的那个条件,
这就使得为什么char * 和char const * 是相容的.

还是举例来说明吧。
char *ch;
char const *cp;
cp=ch;

左值:是有个具有限定符const的指向char型的指针。
右值:是一个没有限定符的char型的指针.
左值是一个char型的指针,右值也是一个char型的指针,左值包含了右值的限定符
即:没有限定符。而char与char是相容的。所以说,char * 和char const * 是
相容的。
而要是您反过来: ch=cp;这个就是不行的了。原因是什么我想我就不用解释了吧?
若是不信的话,您可以去试一试。
好了,现在来解释下接下来的.
还是先来说说这个声明吧:
char const * 类型并不是一个有限定符的类型。它的类型是指向有一个具有const限
定符限定的char型数据的指针,也是就限定的是指针所指的对象,而并不是指针本身.
这跟我上面所说的是一样的,现在只是再来回顾一下。

类似的 char const ** 类型也同样的不是一个有限定符的类型.它表示的是指向一个
具有const限定符限定的指针的指针.
注意:指向类型是char const *
同样char ** 类型,表示指向一个没有任何限定符限的指针的指针.
注意:指向类型是char *

好了,有没有人告诉过您char const * 和char *是同一类型的呢?No...
既然两者都不是同一类型的,那么,它们是不是相容的呢?肯定不是了撒。
所以,这个时候就不可以传过去了咯.


好了,说了那么多的东东,现在又说回来,扯得有一点点远了哈!
我们一次的把多个关于const的弄出来吧!

有了前面的一些认识,现在来弄得深入一点点的.

int const *a;    //a是一个指向 const整型 的指针   
int *const a;    //a是一个指向 整型的 const指针        
int const *const a;    //a是一个指向 const整型的 const指针

嗯?.........好了,现在来一点点稍微复杂的.
int **a;    //a是一个指向 int型指针的指针
int const **a;    //a是一个指向 const int *指针的指针.
int *const *a;    //a是一个指向 int 型的 const 指针的指针.
int **const a;    //a是一个指向 int 型指针的 const指针.
int const *const *a;    //a是一个指向int const 型的 const指针的指针.
int *const *const a;    //a是一个指向int型的 const型指针的const指针.
int const *const *const a;    //a是一个指向int const 型的 const 型指针 的const 型指针.

好了,我想再复杂也不会超过这样子的复杂程度了吧????

本来还想说说volatile的,但是,我想您看到这里应该已经晕了吧?
所以了,下次说volatile吧!平时用这个限定符的时候其实并不多.

 

 

 

From : http://www.52cuit.cn/bbs/viewthread.php?tid=308&extra=page%3D1

<think>好的,我现在需要帮助用户了解JavaScript中const关键字的用法及示例。首先,我要回忆一下const的基本特性。根据引用[3]的内容,const用于声明块级作用域的变量,初始化后不能重新赋值。这意味着一旦给const变量赋值后,就不能再改变它的值了。比如声明const PI = 3.14;之后,再尝试PI = 3.15会报错。 接下来,用户可能需要知道const在对象和数组中的表现。虽然不能重新赋值整个变量,但对象或数组内部的属性或元素是可以修改的。例如,const person = {name: 'Alice'}; person.name = 'Bob'; 这是允许的,但person = {}会报错。这部分需要举例说明,确保用户明白这种细微差别。 然后,关于作用域的问题,const和let一样是块级作用域,不同于var的函数作用域。比如在if块中声明的const变量,外部无法访问。引用[3]中的示例也展示了这一点,函数内部的if块中定义的message在外部访问会报错。 另外,用户可能会混淆const和不可变性。需要明确const只保证变量指向的内存地址不变,而不是值本身不可变。因此,对于引用类型的数据,修改属性是允许的,但重新赋值整个变量不行。这部分可能需要进一步解释,并给出例子。 还有,声明const变量时必须初始化,否则会报错。比如const age; age = 30; 是错误的,必须在声明时赋值。这一点需要强调,避免用户在使用时遇到语法错误。 此外,比较var、let和const的区别也很重要。比如var存在变量提升,而const和let没有;var可以重复声明,const和let不行。这些对比可以帮助用户更好地理解何时使用const。 用户可能还关心在循环中使用const的情况。比如在for...of循环中,每次迭代都会创建一个新的const变量,这可以正常工作。但在传统的for循环中,由于需要改变计数器,不能使用const。这部分可能需要举例说明。 最后,总结const的使用场景:当变量不需要重新赋值时,优先使用const,尤其是在模块导出、配常量、函数表达式等情况下。这有助于代码的可读性和维护性。 现在需要确保回答结构清晰,分点说明,每个点都配有示例代码,并且引用相关的内容来支持。同时,生成的相关问题要围绕用户可能进一步想了解的内容,比如与let的区别、使用场景、对象处理等。</think>### JavaScript const 关键字的用法及示例 #### 1. **基本特性** - **不可重新赋值**:用 `const` 声明的变量必须在声明时初始化,且不能重新赋值。 ```javascript const PI = 3.14; PI = 3.15; // 报错:TypeError: Assignment to constant variable[^3] ``` - **块级作用域**:`const` 声明的变量仅在当前代码块内有效。 ```javascript if (true) { const message = "Hello"; console.log(message); // 输出 "Hello" } console.log(message); // 报错:ReferenceError: message is not defined[^3] ``` #### 2. **引用类型的特殊行为** - **对象或数组可修改内部属性**:虽然变量本身不能重新赋值,但其属性或元素可以修改。 ```javascript const person = { name: "Alice" }; person.name = "Bob"; // 允许 console.log(person.name); // 输出 "Bob" const arr = [1, 2]; arr.push(3); // 允许 console.log(arr); // 输出 [1, 2, 3][^3] ``` - **重新赋值整个变量会报错**: ```javascript person = { name: "Charlie" }; // 报错:TypeError[^3] ``` #### 3. **声明时必须初始化** - 未初始化的 `const` 变量会报错: ```javascript const age; // 报错:SyntaxError: Missing initializer in const declaration ``` #### 4. **与 `let` 和 `var` 的区别** - **作用域**:`const` 和 `let` 是块级作用域,`var` 是函数作用域。 - **变量提升**:`var` 会提升变量声明,`const` 和 `let` 不会。 - **重复声明**:`var` 允许重复声明,`const` 和 `let` 不允许。 ```javascript var x = 1; var x = 2; // 允许 let y = 3; let y = 4; // 报错:SyntaxError[^2] ``` #### 5. **适用场景** - **常量值**:如数学常数、配项。 ```javascript const API_KEY = "abc123"; ``` - **函数表达式**:防止函数被意外覆盖。 ```javascript const sum = (a, b) => a + b; ``` - **模块导出**:确保导出的对象不被替换。 ```javascript export const config = { version: "1.0" }; ``` #### 6. **循环中的使用** - **`for...of` 循环**:每次迭代创建新的 `const` 变量。 ```javascript const numbers = [10, 20, 30]; for (const num of numbers) { console.log(num); // 输出 10, 20, 30 } ``` - **传统 `for` 循环**:不能使用 `const`(因需修改循环变量)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值