当前位置:网站首页>C专家编程 第1章 C:穿越时空的迷雾 1.9 阅读ANSI C标准,寻找乐趣和裨益
C专家编程 第1章 C:穿越时空的迷雾 1.9 阅读ANSI C标准,寻找乐趣和裨益
2022-08-03 16:09:00 【weixin_客子光阴】
阅读ANSI C标准,寻找乐趣和裨益
int foo(const char **p) {
}
编译这段代码,编译器会发出一条警告信息:
int main(int argc, char **argv) {
foo(argv);
}
/*line 5: warning: argument is incompatible with prototype
*prototype: pointer to pointer to const char:
*argument: pointer to pointer to char
*/
/*实参char *s与形参const char *p应该是相容的,标准库中所有的字符串处理函数都是这样的
*实参char **argv与形参const char **p实际上不能相容呢
*答案是肯定的,它们并不相容。
*每个实参都应该具有自己的类型,这样他的值就可以赋值给它所对应的形参类型的对象
*(该对象的类型不能含有限定符)
*这就是说参数传递过程类似于赋值
*所以,除非一个类型为char**的值可以赋值给一个const char**类型的对象,否则肯定会
*产生一条诊断信息。
*/
/*标准中关于简单赋值的部分
*要使上述的赋值形式合法,必须满足下列条件之一:
*两个操作数都是指向有限定符或无限定符的相容类型的指针,左边指针所指向的类型必须
*具有右边指针所指向类型的全部限定符
*/
//合法:
char *cp;
const char *ccp;
ccp = cp;
/*左操作数是一个指向有const限定符的char的指针
*右操作数是一个指向没有限定符的char的指针
*char类型与char类型是相容的,左操作数所指向的类型具有右操作数所指向类型
*的限定符(无),再加上自身的限定符(const)
*/
cp = ccp; /*结果产生编译警告*/
/*const float *类型并不是一个有限定符的类型---它的类型是“指向一个具有const限定符
*的float类型的指针”,也就是说const限定符是修饰指针所指向的类型,而不是指针本身。
*const char **也是一个没有限定符的指针类型,它的类型是“指向有const限定符的char类型的指针的指针”
*char**和const char **都是没有限定符的指针类型,但它们所指的类型不一样(前者指向char*, 后者指向const char *),所以它们是不相容的。因此,类型为char**的实参与const char **的形参是不相容的
*可以用下面这个方法进行理解:
*左操作数的类型是FOO2,它是一个指向FOO的指针,而FOO是一个没有限定符的指针,它指向一个带有const限定符的char类型
*右操作数的类型为BAZ2,它是一个指向BAZ的指针,而BAZ是一个没有限定符的指针,它指向一个没有限定符的char类型
*FOO和BAZ所指的类型是相容的,而且他们本身都没有限定符,所以符合标准的约束条件,两者之间赋值是合法的。
*但FOO2和BAZ2之间的关系又有不同,由于相容性是不能传递的,FOO和BAZ所指向的类型相容并不代表FOO2和BAZ2所指向的内容也相容,所以虽然FOO2和BAZ2都没有限定符,但它们之间不能进行赋值。也就是说,它们都是不带限定符的指针但它们所指的对象是不同的,所以它们不能进行赋值,也就不能分别作为函数的形参和实参。
*/
/*启发 */
/*关键字const并不能把变量变成常量,const 限定符只是表示这个符号不能被赋值,
*也就是它的值对于这个符号来说是只读的,但它并不能防止通过程序的内部(甚至
*是外部)的方法来修改这个值。
*const最有用之处就是它来限定函数的形参,这样该函数将不会修改实参指针所指的
*数据,但其他的函数却可能会修改它。这也许就是C和C++中const最一般的用法。
*/
/*const 可以用在数据上
*const int limit = 10;
*/
/*limitp 是一个指向常量整数的指针,这个指针不能用于修改这个整数值
*但是在任何时候,这个指针本身的值却可以改变。这样,它就指向了不同的
*的地址,对它进行解除引用(dereference)操作会得到一个不同的值
*const和*的组合通常只用于在数组形式的参数中模拟传值调用。
*它声称“我给你一个指向它的指针,但你不能修改它”。
*这个约定类似于从极为常见的void*的用法,尽管在理论上它可以用于任何情形
*,但通常被限制于把指针从一种类型转换为另一种类型。
*const int *limitp = &limit;
*int i = 27;
*limitp = &i;
*/
/*类似地,你可以取一个const变量的地址,并且可以......。正如Ken Thompson所指出的那样,
*“const关键字可能引发一些罕见的错误,只会混淆函数库的接口”。回首往事,const关键字
*原先如果命名为readonly就好多了
*/
#include<stdio.h>
int main()
{
const int limit = 10;
printf( "limit = %d\n", limit );
const int *limitp = &limit;
printf( "*limitp = %d\n", *limitp );
int i = 27;
limitp = &i;
printf( "limit = %d\n", limit );
printf( "*limitp = %d\n", *limitp );
printf( "i = %d\n", i );
return 0;
}
/* 输出:
*/
边栏推荐
猜你喜欢
Introduction to the advantages of the new generation mesh network protocol T-Mesh wireless communication technology
Small Tools (4) integrated Seata1.5.2 distributed transactions
从零开始搭建MySQL主从复制架构
[QT] Qt project demo: data is displayed on the ui interface, double-click the mouse to display specific information in a pop-up window
Windows 事件查看器记录到 MYSQL
面了个腾讯35k出来的,他让我见识到什么叫精通MySQL调优
使用uniapp 封装一个request 请求
#夏日挑战赛# HarmonyOS 实现一个绘画板
【QT】Qt 给已经开发好的程序快速封装成动态库
一个文件管理系统的软硬件配置清单
随机推荐
[Unity Getting Started Plan] Basic Concepts (8) - Tile Map TileMap 01
Kubernetes 笔记 / 入门 / 生产环境 / 容器运行时
To add digital wings to education, NetEase Yunxin released the overall solution of "Internet + Education"
将 Windows 事件日志错误加载到 SQL 表中
GTK实现旋转加载动画
Cookie和Session的关系
STM32的HAL和LL库区别和性能对比
如何使用MATLAB绘制极坐标堆叠柱状图
QT QT 】 【 to have developed a good program for packaging into a dynamic library
不可忽略!户外LED显示屏的特点及优势
【深度学习】今日bug(8月2)
Kubernetes 笔记 / 目录
uniapp隐藏导航栏和横屏显示设置
MySQL查询语法
【Unity入门计划】制作RubyAdventure01-玩家的创建&移动
When mobile applications go overseas, is your "network optimization" holding back?
devops-2:Jenkins的使用及Pipeline语法讲解
罗克韦尔AB PLC RSLogix5000中创建新项目、任务、程序和例程的具体方法和步骤
一文看懂推荐系统:召回03:基于用户的协同过滤(UserCF),要计算用户之间的相似度
Yuan xiaolin: Volvo focus on travel security, and put it perfectly