让我们考虑一下这个片段:
int s;
scanf("%c",&s);
在这里,我使用int
而不是char
来表示变量s
,现在使用s
安全地进行字符转换我必须再次使它成为char,因为当scanf
读取一个字符,它只覆盖它分配给它的变量的一个字节,而不是int
所有的四个字节。
对于转换,我可以使用s = (char)s;
作为下一行但是可以通过从s
减去某些内容来实现相同的内容吗?
答案 0 :(得分:8)
您所做的是技术上未定义的行为。 %c格式调用char *,你已经传递了一个int *,它将(粗略地说)重新解释。即使假设重新解释后指针值仍然很好,将任意字符存储到int的第一个字节然后将其作为int读回是未定义的行为。即使它被定义了,当它的3个字节未初始化时读取int也是未定义的行为。
在实践中,它可能会在你的机器上做一些合理的事情,你只需要在前3个字节中获得垃圾(假设是小端)。
撰写s = (char)s
会将值从int
转换为char
,然后再转回int
。这是实现定义的行为:将超出范围的值转换为有符号的类型。在不同的实现中,它可能会清除前3个字节,它可能会返回其他一些结果,或者它可能会引发信号。
使用scanf的正确方法是:
char c;
scanf("%c", &c);
然后是int s = c;
或int s = (unsigned char)c;
,根据您是希望负值字符产生负整数,还是正整数(最多255,假设8位字符)。
我想不出有任何不正确使用scanf的理由。但是完全不使用scanf是有充分理由的:
int s = getchar();
答案 1 :(得分:1)
这可能不是一个好主意; GCC给了我一个代码警告:
main.c:10: warning: format ‘%c’ expects type ‘char *’, but
argument 2 has type ‘int *’
在这种情况下你没问题,因为你传递的指针比你需要的空间多(对于大多数系统而言),但是如果你以相反的方式做到了怎么办呢?可能是崩溃的城市。如果你真的想做你所拥有的东西,只需进行类型转换或掩盖它 - 掩码将依赖于字节序。
答案 2 :(得分:1)
您是否尝试将数字转换为十进制值?如果是,那么
char c = '8';
int n = c - '0';
n此时应该是8。
答案 3 :(得分:0)
如上所述,这将无法可靠地运作。参数&s
到scanf
是指向int
的指针,scanf期望指向char
的指针。两种数据类型(int
和char
)具有不同的大小(至少在大多数体系结构中),因此数据可能会放在记忆中的错误位置,而s
的另一部分可能无法正常清除。
建议在使用指向int
的指针后操作结果的答案依赖于未指定的行为(即scanf会将其所具有的字符值放在您指向的int的最低有效字节中),并且不安全。
答案 4 :(得分:-1)
不是,你可以使用以下内容:
s = s & 0xFF
除了第一个字节外,这将删除所有数据。但总的来说,所有这些想法(以及上面的想法)都是坏主意,因为并非所有系统都首先将整数的最低部分存储在内存中。因此,如果您必须将此代码移植到大端系统,那么您将被搞砸。
是的,您可能永远不必移植代码,但为什么要编写不可移植的代码?
有关详细信息,请参阅此处: