您正在编码'
sinfully
(犯了很多错误,迟早会伤害到你——大多是更早)。首先,假设整数的尾数是正确的。在某些计算机上,您可能是错误的-在Intel计算机上或在PowerPC或SPARC计算机上。
一般来说,你应该显示你得到的实际结果,而不是仅仅说你得到了错误的结果;你也应该显示预期的结果。这有助于人们调试您的期望。
这是我修改过的代码版本——它不需要请求输入,只采用您指定的值。
#include <stdio.h>
int main(void)
{
unsigned int c = 2249459722;
unsigned char* cptr = (unsigned char*)&c;
printf("Integer value: %10u\n", c);
printf("Integer value: 0x%08X\n", c);
printf("Dotted decimal: %u.%u.%u.%u \n", *cptr, *(cptr+1), *(cptr+2), *(cptr+3));
return(0);
}
在我的Mac(Intel,Little Endian)上编译时,输出为:
Integer value: 2249459722
Integer value: 0x8614080A
Dotted decimal: 10.8.20.134
在Sun上编译时(sparc,big endian),输出为:
Integer value: 2249459722
Integer value: 0x8614080A
Dotted decimal: 134.20.8.10
(在SPARC上使用GCC4.4.2,我得到一个警告:
xx.c:4: warning: this decimal constant is unsigned only in ISO C90
在Mac上使用GCC4.2.1-启用大量警告(
gcc -std=c99 -pedantic -Wall -Wshadow -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Werror
)-我没有收到警告,这很有趣。)我可以通过添加
U
整数常量的后缀。
另一种解决问题的方法是使用下面的代码和上面显示的非常繁琐的编译器设置进行说明:
#include <stdio.h>
static void print_value(unsigned int c)
{
unsigned char* cptr = (unsigned char*)&c;
printf("Integer value: %10u\n", c);
printf("Integer value: 0x%08X\n", c);
printf("Dotted decimal: %u.%u.%u.%u \n", *cptr, *(cptr+1), *(cptr+2), *(cptr+3));
}
int main(void)
{
const char str[] = "2249459722";
unsigned int c = 2249459722;
printf("Direct operations:\n");
print_value(c);
printf("Indirect operations:\n");
if (sscanf("2249559722", "%d", &c) != 0)
printf("Conversion failed for %s\n", str);
else
print_value(c);
return(0);
}
这无法编译(因为
-Werror
设置)带有消息:
cc1: warnings being treated as errors
xx.c: In function âmainâ:
xx.c:20: warning: format â%dâ expects type âint *â, but argument 3 has type âunsigned int *â
移除
-错误
设置并编译,但随后显示下一个问题,即不检查可能失败的函数的错误指示:
Direct operations:
Integer value: 2249459722
Integer value: 0x8614080A
Dotted decimal: 10.8.20.134
Indirect operations:
Conversion failed for 2249459722
基本上,
sscanf()
函数报告它未能将字符串转换为带符号整数(因为该值太大,不适合-请参阅GCC 4.4.2中的警告),但您的代码没有检查返回的错误。
sSCAN()
,所以您使用的是
c
当时。
因此,您的代码存在多个问题:
-
它假设了一个特定的体系结构(小endian而不是承认big endian也存在)。
-
当使用启用了大量警告的编译器时,它不会干净地编译——这是有原因的。
-
它不检查可能失败的函数是否实际成功。
Alok评论
是的,测试在
sSCAN()
是错的。这就是为什么您有代码评审,以及为什么它有助于发布您正在测试的代码。
我现在有点困惑了——我无法立即解释始终如一的行为。有了明显的修改(在MacOS X 10.6.2、GCC4.2.1、32位和64位编译上测试),我得到了一个不太明智的答案。当我更模块化地重写时,我得到了一个明智的答案。
+ cat yy.c
#include <stdio.h>
static void print_value(unsigned int c)
{
unsigned char* cptr = (unsigned char*)&c;
printf("Integer value: %10u\n", c);
printf("Integer value: 0x%08X\n", c);
printf("Dotted decimal: %u.%u.%u.%u \n", *cptr, *(cptr+1), *(cptr+2), *(cptr+3));
}
int main(void)
{
const char str[] = "2249459722";
unsigned int c = 2249459722;
printf("Direct operations:\n");
print_value(c);
printf("Indirect operations:\n");
if (sscanf("2249559722", "%d", &c) != 1)
printf("Conversion failed for %s\n", str);
else
print_value(c);
return(0);
}
+ gcc -o yy.32 -m32 -std=c99 -pedantic -Wall -Wshadow -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes yy.c
yy.c: In function âmainâ:
yy.c:20: warning: format â%dâ expects type âint *â, but argument 3 has type âunsigned int *â
+ ./yy.32
Direct operations:
Integer value: 2249459722
Integer value: 0x8614080A
Dotted decimal: 10.8.20.134
Indirect operations:
Integer value: 2249559722
Integer value: 0x86158EAA
Dotted decimal: 170.142.21.134
对于值170.142.21.134,我没有很好的解释;但目前在我的机器上是一致的。
+ gcc -o yy.64 -m64 -std=c99 -pedantic -Wall -Wshadow -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes yy.c
yy.c: In function âmainâ:
yy.c:20: warning: format â%dâ expects type âint *â, but argument 3 has type âunsigned int *â
+ ./yy.64
Direct operations:
Integer value: 2249459722
Integer value: 0x8614080A
Dotted decimal: 10.8.20.134
Indirect operations:
Integer value: 2249559722
Integer value: 0x86158EAA
Dotted decimal: 170.142.21.134
相同的值-即使是64位而不是32位。也许问题是我试图解释不明确的行为,这或多或少是由定义无法解释(无法解释)。
+ cat xx.c
#include <stdio.h>
static void print_value(unsigned int c)
{
unsigned char* cptr = (unsigned char*)&c;
printf("Integer value: %10u\n", c);
printf("Integer value: 0x%08X\n", c);
printf("Dotted decimal: %u.%u.%u.%u \n", *cptr, *(cptr+1), *(cptr+2), *(cptr+3));
}
static void scan_value(const char *str, const char *fmt, const char *tag)
{
unsigned int c;
printf("Indirect operations (%s):\n", tag);
fmt = "%d";
if (sscanf(str, fmt, &c) != 1)
printf("Conversion failed for %s (format %s \"%s\")\n", str, tag, fmt);
else
print_value(c);
}
int main(void)
{
const char str[] = "2249459722";
unsigned int c = 2249459722U;
printf("Direct operations:\n");
print_value(c);
scan_value(str, "%d", "signed");
scan_value(str, "%u", "unsigned");
return(0);
}
使用这样的函数参数意味着gcc不能再发现伪造的格式了。
+ gcc -o xx.32 -m32 -std=c99 -pedantic -Wall -Wshadow -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes xx.c
+ ./xx.32
Direct operations:
Integer value: 2249459722
Integer value: 0x8614080A
Dotted decimal: 10.8.20.134
Indirect operations (signed):
Integer value: 2249459722
Integer value: 0x8614080A
Dotted decimal: 10.8.20.134
Indirect operations (unsigned):
Integer value: 2249459722
Integer value: 0x8614080A
Dotted decimal: 10.8.20.134
这里的结果是一致的。
+ gcc -o xx.64 -m64 -std=c99 -pedantic -Wall -Wshadow -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes xx.c
+ ./xx.64
Direct operations:
Integer value: 2249459722
Integer value: 0x8614080A
Dotted decimal: 10.8.20.134
Indirect operations (signed):
Integer value: 2249459722
Integer value: 0x8614080A
Dotted decimal: 10.8.20.134
Indirect operations (unsigned):
Integer value: 2249459722
Integer value: 0x8614080A
Dotted decimal: 10.8.20.134
这些和32位的情况是一样的。我正式感到困惑。主要观察结果仍然准确-小心,注意编译器警告(并引发编译器警告),不要假设“所有的世界都在英特尔芯片上运行”(很久以前它曾是“不要假设所有的世界都是一个VAX”)。.