`
kofsky
  • 浏览: 201670 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

'char **' 和 'const char **'的兼容性问题

SUN 
阅读更多

有时候必须非常专注的阅读ANSI C 标准才能找到某个问题的答案。一位销售工程师把下面的代码作为测试例子发给SUN的编译器小组。<!----><o:p></o:p>

#include<stdio.h><o:p></o:p>

<o:p> </o:p>

void foo( const char **P )<o:p></o:p>

{}<o:p></o:p>

<o:p> </o:p>

int main( int argc, char **argv )<o:p></o:p>

{<o:p></o:p>

    foo( argv );<o:p></o:p>

return 0;<o:p></o:p>

}<o:p></o:p>

<o:p> </o:p>

VC6.0下编译这段代码,编译器会发出警告:<o:p></o:p>

cannot convert parameter 1 from char ** to const char **

<o:p></o:p>
<o:p></o:p>
<o:p></o:p>

<o:p> </o:p>

<o:p> </o:p>

提交代码的工程师想知道为什么会产生类似的警告,他认为,实参char *s 与形参 const char *p 应该是相容的,标准库中所有的字符串处理函数都是这样的。那么,为什么实参 char **argv 与形参 const char **P实际上不能相容呢?答案是肯定的,它们并不相容。现在我们回顾一下标准中有关简单赋值的部分,它位于ANSI C <!----><st1:chsdate isrocdate="False" month="12" w:st="on" islunardate="False" day="30" year="1899">6.3.16</st1:chsdate>.1节,描述了下列约束条件:<o:p></o:p>

要使上述赋值形式合法,必须满足下列条件之一:<o:p></o:p>

两个操作数都是指向有限定符或无限定符的相容类型的指针,左边指针所指向的类型必须具有右边指针<o:p></o:p>

所指向类型的全部限定符。<o:p></o:p>

正是这个条件,使得函数调用中实参char*能够与形参const char*匹配。它之所以合法,是因为在下面的代码中:<o:p></o:p>

char *cp;<o:p></o:p>

const char *cpp;<o:p></o:p>

cpp = cp;<o:p></o:p>

    左操作数是一个指向有const限定符的char的指针;<o:p></o:p>

    右操作数是一个指向没有限定符的char的指针;<o:p></o:p>

    char类型和char类型是相容的,左操作数所指向的类型具有右操作数所指向类型的限定符(), 再加上自身的限定符 const (注意反过来不能赋值)<o:p></o:p>

<o:p> </o:p>

标准第<st1:chsdate isrocdate="False" month="12" w:st="on" islunardate="False" day="30" year="1899">6.3.16</st1:chsdate>.1节没有说明char **实参与const char **形参是否相容。标准6.1.2.5节中讲述实例的部分声称:const float * 类型并不是一个有限定符的类型,它的类型是“指向一个具有const限定符的float类型的指针”,也就是说const限定符是修饰指针所指向的类型,而不是指针。类似地,const char **也是一个没有限定符的指针类型,它的类型是“指向有const限定符的char类型的指针的指针”。 由于char ** const char ** 都是没有限定符的指针类型,但它们所指向的类型不一样(前者指向char *,后者指向 const char *,因此它们是不相容的。因此类型为char **的实参和类型为 const char **的形参是不相容的,编译器会产生一条诊断信息。

<o:p></o:p> 

备注:解释的有些牵强,目前记住结果就可以了

 

<o:p></o:p> 

分享到:
评论

相关推荐

    const char*转LPCWSTR 字符串转换

    因此,当你的代码中只有`const char*`字符串时,需要进行转换才能与这些API接口兼容。 转换方法主要有两种:使用`MultiByteToWideChar`函数和使用`wcstombs`函数。 1. 使用`MultiByteToWideChar`函数: 这是...

    wchar_t*转换为char*

    当需要在两者之间进行转换时,必须采取适当的方法以确保数据的正确性和兼容性。以下是一些关于如何将 `wchar_t*` 转换为 `char*` 的详细知识点: 1. **宽字符和窄字符的区别** - **宽字符(`wchar_t`)**: 宽字符...

    VC++不同数据类型的转换

    ### VC++ 不同数据类型的转换 #### 概述 在VC++编程中,经常需要处理各种数据类型...此外,对于跨API的转换,如从BSTR转换到`char*`,则需要考虑使用的库及其兼容性问题。掌握这些转换方法对于日常编程工作非常有用。

    CString,string,char的综合比较

    对于新项目而言,推荐使用 C++ 标准库中的 `string` 类,因为它具有更好的性能、更多的功能以及更好的跨平台兼容性。而对于旧的基于 MFC/ATL 的项目,可能仍然需要使用 `CString`。对于简单的字符串操作,直接使用 `...

    ExceptionEx

    此外,为了保持与`std::exception`的兼容性,它可能还会包含一个`what()`成员函数,返回一个描述异常的字符串。为了提供源代码信息,`ExceptionEx`可能还包含成员变量来存储文件名、行号和函数名,这些信息在构造...

    C语言实现ini文件读写操作(C语言)

    在IT领域,C语言是一种基础且强大的...这种实现方法虽然相对简单,但在实际项目中可能会遇到性能、安全性及兼容性等问题,因此在处理大文件或高并发场景时,可能需要优化或采用更专业的库,如libconfig或tinyconf等。

    C/C++ 读写INI配置文件源代码

    7. 兼容性:由于标题提到“不限制编译环境”,这意味着源代码可能使用了标准C++库,避免了特定平台的依赖,增强了可移植性。 8. 性能优化:可能采用了内存缓冲、流式读写等技术提高读写性能,同时保持代码简洁。 ...

    嵌入式工程师转正试题.docx

    - 使用适当的间距规则,避免电气短路和电磁兼容问题。 - 尽量使关键元器件靠近,缩短高速信号路径。 - 注意元器件热耗散,避免热点产生。 - 添加适当的过孔和通孔,确保电气连接。 - 对于高频信号,考虑使用...

    C++程序员应聘常见面试题剖析

    char *strcpy(char *strDest, const char *strSrc) { assert((strDest != NULL) && (strSrc != NULL)); char *address = strDest; while ((*strDest++ = *strSrc++) != '\0'); return address; } ``` #### 四、...

    QT常用控件编程.docx

    需要注意的是,这里使用的是`QLatin1String`而非`QString::fromLatin1()`,但在实际代码中推荐使用`QString::fromLatin1()`以提高兼容性。 2. **从QString转换到char ***: ```cpp QString str = "Hello"; const...

    (UNICODE 与非UNICODE导致的问题)CString,TCHAR和CHAR类型的互转.docx

    正确处理`CString`、`TCHAR`和`CHAR`之间的转换对于确保代码在UNICODE和非UNICODE环境下的兼容性至关重要。不正确的转换可能导致乱码或者程序运行错误。在编写跨平台或需要兼容不同编码的代码时,这些转换函数是必不...

    C++/C基本编程技能

    2. **C++与C的兼容性** - C++兼容C语言,但某些C++特性(如类和对象)在C中不可用。 - `extern "C"`:在C++中使用此声明可以确保编译器以C链接约定处理函数,以确保与C代码兼容。 ##### 四、循环结构优化 考虑...

    QRCODE 单片机实现二维码显示

    此外,为了保证二维码的可读性,还需要注意屏幕的亮度和对比度设置,以及扫描设备的兼容性。在实际应用中,可能需要进行多次调试以达到最佳效果。 总之,单片机实现二维码显示涉及到C语言编程、LCD驱动、二维码编码...

    浅谈const变量赋值报错分析

    当遇到编译错误时,应当仔细检查变量的`const`修饰符以及赋值操作是否符合类型兼容性规则。同时,谨慎使用`const_cast`,以防止潜在的危险。在类中声明`const`变量时,务必确保它们在构造函数中得到初始化,或者考虑...

    memcpy函数的实现代码 (2).pdf

    它的基本语法是`void *memcpy(void *dest, const void *src, size_t n)`,参数分别是目标地址、源地址和要复制的字节数。在面试中,理解和熟悉memcpy的内部机制以及如何优化实现是非常重要的。 首先,我们来看原始...

Global site tag (gtag.js) - Google Analytics