C语言const
lonely-hermit 人气:0一、int const a / const int a
int 和const 都作为一个类型限定词,有相同的地位,所以谁在前谁在后无所谓了,标题中的这两种写法是一致的。
这是我们常规的用途,我们发现这样的话我们对a已经不能做任何修改了。
int main() { int const a = 10; printf("%d\n",a); return 0; }
真的不能修改吗?未必的
int main() { int const a = 10; int *p = &a; *p = 20; printf("%d\n",a); return 0; }
成功修改,这是为什么呢,其实也很简单,这与编译器有关,gcc编译器中const是通过编译器在编译的时候执行检查来确保实现的,也就是检查的时候我发现你没有修改a的值,那我就认为你是对的。更深入一层的原因,是因为gcc把const类型的常量也放在了data段,其实和普通的全局变量放在data段是一样实现的,只是通过编译器认定这个变量是const的,运行时并没有标记const标志,所以只要骗过编译器就可以修改了。
这个本质上是C语言的问题,因为C语言就没有强制要求说const就是不能修改的,所以在C语言中使用const,就好象是 一种道德约束而非法律约束,所以大家使用const时更多是传递一种信息,就是告诉编译器、也告诉读程序的人,这个变量是不应该也不必被修改的。而且我的理解中,这个东西其实设置为了强制不可变在某种程度上不也就限制了C语言的灵活性嘛,c的奇淫巧技不就依靠C语言的灵活性实现的嘛,所谓bug变特性,我的猜测哈,不知道丹尼斯·里奇是不是也是这么想的。
二、const int(*p)/int const(*p)
其实标题是很好理解的,我们修饰了*p,使得p的指向不能被改变了。
int main() { int a = 10; int const (*p) = &a; printf("%d\n",*p); return 0; }
上面的程序很好理解,p指向了a,p被const修饰,指向的对象a已经不能被修改了,下面的程序输出20就说明出了问题,这个还是上面我们讲到的那个问题,这是一个君子约定。
int main() { int a = 10; int const (*p) = &a; a = 20; printf("%d\n",*p); return 0; }
下面的四种写法等价
int const (*p)
const int (*p)
int const *p
const int *p
三、int*const p
那么如何声明一个自身是常量指针呢?方法是让const尽可能的靠近p,下面的这个就是
int main() { int a = 10; int b = 20; int* const p = &a; printf("%d\n",*p); return 0; }
指针只能指向a,指向b就报错。地址只能赋值一次。
这里有一个简便的区分方法:沿着*号划一条线,如果const位于*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量.如果const位于*的右侧,const就是修饰指针本身,即指针本身是常量。
四、const用于函数的地址传递参数
void func(const int *p);
这种形式通常用于在数组形式的参数中模拟传值调用。也就是相当于函数调用者声称:"我给你一个指向它的指针,但你不能去修它。"如果函数编写者遵循了这个约定,那么就相当于模拟了值传递。这也是const最有用之处了:用来限定函数的形参,这样该函数将不会修改实参指针所指的数据。这里注意了,是函数不应该去修改而不是不能修改,也就是说const不能阻止参数的修改(原因见上)。
加载全部内容