【问题标题】:Is char variable always represented as dereferenced char*[2] with {'x',\0}?char 变量是否总是用 {'x',\0} 表示为取消引用的 char*[2]?
【发布时间】:2016-01-20 11:20:27
【问题描述】:

我尝试了这种方法将 char 数字转换为整数数字 ('3'->3),它似乎有效。

char c='x';
int i=atoi(&c);

我的问题是,这会一直有效吗?

在第一个字符之后总是有一个 NULL 字符吗?

还有另一种使用隐式类型转换的方法,但我不确定这是一个好习惯。实际上,我很惊讶即使使用 -Wall 和 -Wextra 也没有警告。

int i = c - '0';

注意我使用的是 GCC 4.8.2 和 MinGW。

【问题讨论】:

  • 这几乎是未定义的行为。它之所以有效,是因为可能越界访问的内存的值为 0。
  • 对于第二种情况,C和C++ guarantees the order of digit characters
  • 您混淆了字符串和字符。 char 始终是单个字符。
  • 请选择 C ​​和 C++ 之一。
  • @FUZxxl 有区别吗?我对两者都感兴趣。

标签: c++ c c++11 casting char


【解决方案1】:

这可以编译,但它是未定义的行为。

char 只是一个字符。后面没有空字节。不过,std::atoi 需要一个空字节,因此调用 std::atoi(&c) 会编译但会产生未定义的行为。这一行,

int i = std::atoi("x");

但定义明确,因为字符串 "x"char[2] 并且以空值结尾。

int i = c - '0';

没关系,因为1C++11 standardC99 standard2 保证了字符数字的顺序。


1 正如@ShafikYaghmour 在您的问题的 cmets 中指出的那样

2再次感谢@ShafikYaghmour!

【讨论】:

  • @Slazer 这是未定义的行为。它可能有效,但它也可以让恶魔飞出你的鼻子。
  • @Slazer 啊,我明白了,这就是你的意思。会澄清这一点。
  • 好吧,它可能会起作用,而且它适用于我的情况。所以“这根本行不通”的说法是错误的。不过,我明白什么是未定义的行为。
  • @Slazer 好的,已修复。
  • C version of the question 按数字顺序排列。
【解决方案2】:

atoi 需要以空字符结尾的 C 字符串。

因为你没有提供它(你提供了一个指向字符的指针)这是未定义的行为。

对于第二行代码 - 如果您可以保证字符确实是数字,这通常会起作用。例如,字符# 会产生结果,但可能不是您期望的结果。

一些解决方案是使用std::stoi:

try{ int x = std::stoi(std::string() + c) } catch(...) {/*handle*/}

【讨论】:

  • 在我看来,对于这样一个简单的任务来说,使用字符串太重了。不过,异常功能看起来不错。
【解决方案3】:

只要分配 c 的内存空间旁边是 \0,这将起作用。换句话说,这只是运气。你应该使用int i = c - '0'

但请注意,每个字符都将映射到 int (f.e. int i = 'a' - '0')

为避免这种情况,您可以执行以下操作:

int i = c=>'0' && c<='9' ? c-'0' : -1; //-1 represents not valid values

【讨论】:

  • 很可能是因为您声称未定义的程序可以运行。存储在&amp;c + 1 中的实际值(可能)无关紧要,因为访问它具有未定义的行为。
  • 但这解释了为什么他的程序有效(至少在 OP 测试时)。未定义的行为!= 不工作,在最好的情况下它不会工作,在最坏的情况下它会在你测试它并在稍后崩溃时工作(像这样)
猜你喜欢
  • 2010-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-09
  • 2013-07-26
  • 2013-07-15
相关资源
最近更新 更多