我正在尝试使用相同的方法mentioned here来大写std::string
的第一个字符。例如,对于以下程序
#include <cctype>
#include <iostream>
#include <string>
int main()
{
std::string name = "foobar";
name[0] = std::toupper(name[0]);
std::cout << name;
}
我期待输出
Foobar
当我compile this online(使用GCC 4.9.2)时,我得到正确的输出,没有任何警告。但是,当我在Visual Studio 2013中编译相同的代码时,我在从toupper
warning C4244: '=' : conversion from 'int' to 'char', possible loss of data
上述方法是否符合C ++标准或警告是否正确?否则这只是Visual Studio的错误警告?
答案 0 :(得分:2)
std::toupper
来自C标准,而不是C ++,并且有一个讨厌的界面,它需要并返回int
而不是char
。使用static_cast<char>(std::toupper(name[0]))
将适合您。
答案 1 :(得分:2)
到目前为止,警告是正确的;标准中定义的std::toupper
类型为:
int toupper( int ch );
主要是因为它是来自黑暗C年龄的残余物(cctype
标题是对此的暗示)。
然而,这只是故事的一部分。 toupper
标题中存在另一个 locale
:
template< class charT >
charT toupper( charT ch, const locale& loc );
这个不应该给你任何警告。如果您不确定要提供的区域设置,std::locale()
将为您提供默认区域设置。
答案 2 :(得分:1)
警告是正确的,编译器将隐式地从int转换为char,但在某些情况下这可能会导致数据丢失。要查看gcc
下的警告,您需要添加-Wconversion编译器选项。这会产生:
main.cpp: In function 'int main()':
main.cpp:8:13: warning: conversion to '__gnu_cxx::__alloc_traits<std::allocator<char> >::value_type {aka char}' from 'int' may alter its value [-Wconversion]
name[0] = std::toupper(name[0]);
^
Foobar
设置-Wall时为什么不存在,请在此处阅读:
https://gcc.gnu.org/wiki/NewWconversion
为什么不通过-Wall或至少-wextra启用Wconversion?
隐含转换在C中非常常见。这与事实相关 前端没有数据流(见下一个问题)结果 很难避免完美工作和有效代码的警告。 Wconversion专为一系列用途而设计(安全审计,移植) 程序员愿意接受的32位代码到64位等 和解决方法无效警告。因此,如果不应该启用它 没有明确要求。