为什么“const int”到“int”转换有效但“const char []”到“char *”却没有

时间:2014-11-08 15:29:52

标签: c++ char int type-conversion const

这总是引起我对C ++语言的兴趣。随着" const"的出现标识符,它应该替换使用#define语句来声明常量。但正如我所说,使用它们,我最终在一个const char to char转换错误疯狂。

最近,我说过在Java中完成的类常量。所以我决定宣布这样的事情。

private: const static int NB_FIELD = 22;

这完美无缺。返回int的函数可以返回" const int"没有任何问题。

但是现在如果我尝试用这样的字符串做同样的事情:

private: static const char ERRORSTR [ 6 ];

哪个字符串"错误",它会生成const char to char转换问题,就像在这个函数中一样。

char* EnhancedSQLobject::get_SQLname ( int index )
{
   if ( index < p_nb_field && index >= 0 )
      return ( p_SQLfield_ptr [ index ] . SQLname)

   return ( ERRORSTR );

}

现在有些人会说更改const char *的返回值但是我不能,因为如果索引有效,它将返回一个非const变量,但如果索引无效,它将返回一个常量错误字符串。

所以我的选择是使错误字符串非常量,或者使用#define语句创建常量。我记得很久以前我试图将所有东西定义为一个const char,但最终它在转换链中的其他地方爆炸了。使用常规字符更容易(String类不适合我)

这简直荒谬,为什么要实现仅适用于部分变量类型的功能。我想这与蜇实际上是字符表的事实有关,所以它可能会返回指针而不是值。

3 个答案:

答案 0 :(得分:2)

在一个案例中,您正在谈论将const int投射到int,而另一个案例则是const char*投射到char*。这些实际上是不同的情况应该表现不同,因为后者具有添加的间接级别(指针)。您绝对可以将const char投射到char,但这不是您正在做的事情。

考虑以下错误代码:

const int i = 50;
int j = i;
int* p = &i; // ERROR

我尝试int j = i;,这很好。原始i对象仍为constj对象的值与i相同。但是,如果我尝试int* p = &i;,我们就会遇到问题。如果这会编译,我们会p指向const int,即使它告诉我们它指向非const int。这将允许我们通过指针i修改const对象p - 这非常糟糕。

这里的情况与char s相同。您char中的所有ERRORSTR都是const。然后,您无法返回指向char*中任意一个的char,因为那将是谎言。指针不是指向非常量char,而是指向const个字符。

在这方面,

intchar并没有任何不同。

但是,我认为由于界面设计不佳,你才进入了这种困境。为什么你的函数在找不到&#34; SQLname&#34;时会返回一个特殊的字符串。 (不管那是什么)?例如,如果字符串&#34;错误&#34;实际上是一个有效的名字?函数的调用者将如何区分?我认为,如果你的功能无法完成get_SQLname的操作(也就是说,它无法获取名称),那么它应该抛出异常。

除此之外,您应该使用std::string而不是C风格的char*

答案 1 :(得分:0)

两次转化之间存在差异。对于int

const int ci = 7;
int i = ci; // fine...
++i;        // ... because ci is still 7

但是如果你可以为char*执行此操作:

const char msg[] = "Hi";
char* p = msg; // not OK...
*p = 'B';      // ... because now msg = "Bi" 
               //     and it was supposed to be const!

指针的实际等价物是:

char * const cc = someBuf();
char * c = cc; // this is totally OK
++c;           // ... because we're not modifying cc in any way

这是const指针和指向const的指针之间的区别。

答案 2 :(得分:0)

您知道,使用#define将无法正常工作,至少在您真正使用C ++而非C时无法使用。

在C ++中,字符串文字是const,因此如果你声明:

#define ERRORSTR "ERROR"

如果您尝试修改返回的字符串,则尝试从return ERRORSTR get_SQLname,它可能会导致未定义的行为。您的编译器很可能只是发出警告,因为字符串文字const这一事实在很久以前的C ++中并不总是正确的。

#include <iostream>

#define BLAH "blah"

char *foo() {
    return BLAH;
}

int main(int argc, char *argv[]) {
    std::cout << foo() << std::endl;
}

在我的编译器上,我看到以下警告:

so.cpp:6:12: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]

现实情况是,使用#define作为常量,尤其是字符串常量,由于这个原因是不安全的,因此应该避免。 const为编译器提供了一定程度的安全性,如果编译器告诉你转换是不安全的,那么就有这个错误的原因,你应该试着找出原因并解决问题而不是只是试图使错误沉默或找到其他一些解决方法。实际上,依赖C语言中的行为通常是C ++中的代码味道,并且依赖于Java之类的另一种语言的语义甚至更糟。尽管它们在语法上有相似之处,但Java,C和C ++在它们的实际语义上都是非常不同的。您最好学习这些差异,而不是仅仅尝试将您熟悉的知识应用于另一种语言。