2010-10-28 107 views
1

我有以下代码,但我得到不正确的输出。 有谁能告诉我为什么输出只有10 B,为什么我没有得到A的输出?如何将两个变量的int地址转换为C中的char指针?

#include<stdio.h> 
#include<conio.h> 
void main() 
{ 
    int *p; 
    char c,d; 
    int i; 

    clrscr(); 
    p=&i; 
    *p=10; 
    (char *)p=&c; 
    *p=65; 
    (char *)p=&d; 
    *p=66; 
    printf("%d%c%c",i,c,d); 
    getch(); 
} 
+0

是'残培()'在Windows关闭命令提示符之前等待用户输入? – 2010-10-28 05:38:35

+0

这是一个特定于平台的问题,所以应该提供该信息(操作系统,编译器等) – 2010-10-28 05:40:22

回答

5

您的程序调用未定义的行为,所以没有正确或不正确的行为。具体做法是:

*p = 65; 

写入的整数到内存中,只有一个char室。 C99§6.5.3.2/ 4(地址和间接操作)状态:

如果操作数具有type''类型''的指针,则结果的类型为'type''。如果无效值已被分配给所述指针,一元运算符*的行为是理解过程音响ned.84)

p有类型指针int,所以*p具有类型int。但是,p不是有效的int对象的地址。

另外,我相信作业左侧的剧组是非法的(GCC肯定是这么认为的)。

我相信发生的事情是,它奠定了(增加addressess),如:

|i|i|i|i|d|c|p|p|p|p| 

这代表分别占用的字节数。我会通过什么,我认为正在发生的事情走路:

p = &i; 

|i|i|i|i|d|c|00|00|00|00| 

为简单起见,我假设的i地址为0

*p=10; 

|10|0|0|0|d|c|00|00|00|00| 

p=&c; 

|10|0|0|0|d|c|05|00|00|00| 

*p=65; 

|i|i|i|i|d|65|00|00|00|00| 

请注意,修改*p覆盖p

p=&d; 

|10|0|0|0|d|65|04|00|00|00| 

*p=66; 

|10|0|0|0|66|00|00|00|00|00| 

所以存储到d覆盖c用NULL。如果你的机器是小端的,有4个字节的整数,并且堆栈向上(朝着低地址)增长,上述情况适用。如果您有2个字节的整数,分析是不同的,但主要结论仍然适用。

返回void也是非法的,但这是无关的。

+0

我不认为这里的int的赋值可能是问题。他们都在'char'的保证范围内,不是?只要这种分配的价值符合,就没有不确定的行为。顺便说一句,“a”或“\ n”是“int”。 – 2010-10-28 07:09:55

+0

@Jens,不,范围无关紧要。存储一个int(即在'='左边有一个int)仍然会写入'sizeof(int)'字节。我知道像“a”这样的字符常量是整数。 – 2010-10-28 07:13:00

+0

啊,对不起,我可能误读了,然后。 – 2010-10-28 07:36:16

0

我无法编译你的程序,它不符合ANSI标准。这里是固定版本,它打印“10AB”:

#include<stdio.h> 

int main() 
{ 

int *p; 
char *cp; 
char c,d; 
int i; 
p=&i; 
*p=10; 
cp=&c; 
*cp=65; 
cp=&d; 
*cp=66; 
printf("%d%c%c\n",i,c,d); 
} 
-1

您正在以错误的方式使用铸造操作符。你把一个char *赋给int *。所以你应该使用char *来允许转换。正确的代码如下:

int *p; char c,d; int i; 
p=&i; 
*p=10; 
p=(int *)&c; 
*p=65; 
p=(int *)&d; 
*p=66; 
printf("%d%c%c",i,c,d); 
+0

该代码仍然通过存储'int'来调用未定义的行为,只有'char'符合。 – 2010-10-28 06:01:07

3

声明(char *)p=&c;不会奇迹般地变成pchar *,从这一点上。在下一行*p=65;中,您仍然会将int放入该位置。

同上(char *)p=&d; *p=66;。现在,因为你将什么是几乎可以肯定两个字节到单字节d,你可能覆盖c以0

你会发现改变*p = 66*((char*)p) = 66会给你想要的东西,一个插入字节。

而且,请尽可能升级到gcc。它的成本与Turbo C完全相同,并且每的方式更便宜大约

1

你想用

p = (int *) &c; 

但是当你做

*p = 65 

那么编译程序将投入65,作为一个4字节的值(假设你的int是4字节)到内存c居住。它会再浪费3个字节......因为c只有1个字节,并且你将4个字节的数据放入其中...并且我怀疑某个平台是否会投诉,因为c是一个字符,并且可能不是int边界...

你可能想使用

char *pChar = &c; 
*pChar = 65; 

如果你想将一个字节65到整数i实验,您可以使用

pChar = (char *) &i; 
*pChar = 65; 

(char *)被称为铸造 - 使它成为一个指向角色的指针。

0

您的主要问题是整个事情是一个黑客。不要这样做。没有理由像这样来回转换intchar。你只能从编写代码的方式期待麻烦。

一些提示:

  • 正确包括标准 C文件是stdio.h
  • 用C
  • 表达(char*)p不是 左值,这意味着你不能 分配给它。 (这有很好的理由)
  • 即使你会成功的分配 一个char的地址到int 指针这个情况一般一个坏主意 。不仅因为你会 最终覆盖的内存是 不是“你的”,也是因为 对齐问题。可以 发生在你在这样的情况下,最好是 bus error,提前告诉你, 你是在错误的轨道上
  • main返回类型为int