2013-06-24 66 views
2

我是学习指针的初学者。这是我的代码。 (注:我仍然在试图让我的头周围的指针,所以我的代码不会是干净的。)C编程简单指针

#include <stdio.h> 
#include <stdlib.h> 

int main (int argc, char *argv[]){ 

int a = 1; 
char b = 's'; 
double c = 3.14; 
int *ptra; 
int *ptrb; 
int *ptrc; 

ptra = &a; 
ptrb = &b; 
ptrc = &c; 

printf("I initialised int as %d and char as %c and double as %.2f\n", a, b, c); 
printf("The address of A is %p and the contents of A is %d\n", ptra, *ptra); 
printf("The address of B is %p and the contents of B is %c\n", ptrb, *ptrb); 
printf("The address of C is %p and the contents of C is %.2f\n", ptrc, *ptrc); 

我期待下面的输出:

I initialised int as 1 and char as s and double as 3.14 
The address of A is 0xbf933094 and the contents of A is 1 
The address of B is 0xbf933093 and the contents of B is s 
The address of C is 0xbf933098 and the contents of C is 3.14 

而是我得到这个:

I initialised int as 1 and char as s and double as 3.14 
The address of A is 0xbf933094 and the contents of A is 1 
The address of B is 0xbf933093 and the contents of B is s 
The address of C is 0xbf933098 and the contents of C is 427698.00000 

有人可以帮我打印C的内容时得到的大数?为什么我不能得到3.14? (这个数字实际上比这个长,但它不适合这个文本框。:-))

+1

我想你想要一个双指针,而不是int。 –

+0

我有一种感觉,它与指针'ptrc'设置为指向'int'数据类型的事实有关,但实际上它指向了'double'数据类型。 “int”通常是4个字节,“double”是8个字节。指针正在查看4个字节的信息,但它必须读取所有8个字符才能获得'double'的真实值。为了“解决”问题,将'ptrc'声明为'double'。 – brazilianldsjaguar

+3

这里的大多数答案都没有提到。发生此问题的原因是sizeof(double)> sizeof(int),导致浮点值尾数中的位被截断。 –

回答

2

你的指针都是int。这是不正确的。替换那些

int *ptra; 
char *ptrb; 
double *ptrc; 
+0

谢谢!愚蠢的错误在我的角色。对不起:-) – Bobby

5

您声明ptraptrbptrc为指针int秒。但指针的类型是基于什么它指向,所以它真的应该是:

int *ptra; 
char *ptrb; 
double *ptrc; 

在你具体情况下,你的程序试图通过int指针来解释double值。由于这些数据类型的大小在您的机器上有所不同,双倍数据的某些位会被丢弃,最终会出现您所看到的奇怪数字。

这可能不总是以同样的方式发生 - 通过错误类型的指针访问某些东西的结果不是由C语言定义的,但它仍然可以编译。 C程序员将此称为未定义的行为(如果您想学习C,您应该真正了解一个短语)。

还有一个事实,即当您拨打printf时,您需要为其指定格式字符串所需类型的变量。所以,如果你给它一个格式字符串,其中第占位%.f,你必须它,这是一个双重的第一参数。如果不这样做,printf也将表现出不确定的行为,并可以做任何事情(未定义行为可能是陌生的输出,崩溃,或者干脆把出您所期望的数量......直到最糟糕的时刻)。

+0

谢谢。当你提到未定义的行为时,你的意思是世界上没有办法预测它会输出什么? – Bobby

+0

@Bobby:这并不是说没有办法预测行为;这是标准没有指定行为,所以程序是“格式不正确”的,编译器可以自由地做任何事情,而不是记录它会做什么。 –

+1

@Bobby - 呃...有点。你不应该试图预测会发生什么。如果你对你的特定编译器和你的程序运行的机器有足够的了解,你通常可以说出会发生什么。但这是愚蠢的游戏,你应该坚持使用便携式代码。 – detly

2

因为你的指针都是int*。如果你想将它解引用到double,你需要它是double*。您的编译器应该已经警告过有关不兼容的指针分配。

1

你应该使用声明相应类型的指针。

int *ptra; 
char *ptrb; 
double *ptrc; 
1

您需要更改指针类型以匹配您的数据类型,以便相应地设置大小。

char *ptrb; 
double *ptrc; 
0

如果我只能说一些关于键入指针的话。

指针与类型(而不是void*指针)知道有多少字节在内存中前进。例如,在32位系统上,当遍历包含整数值的数组时,整数指针通常会在内存中前进四个字节。

字符指针(由C标准保证始终为1个字节)自然会一次提前1个字节。

让我说明这个有一小段代码:

#include <stdio.h> 

int main() 
{ 
    char array [] = "This is a char array."; 

    int* int_ptr; 

    char* char_ptr; 

    char_ptr = array; /* This is okay, we have a char array and we assign its address to a char pointer */ 

    int_ptr = array; /* It will complain but let's go along with it */ 

    printf("%p, %p, %p\n", array, char_ptr, int_ptr); /* They should all point to the same address in memory */ 

    printf("%p\n", ++char_ptr); /* it will have advanced by one byte */ 

    printf("%p\n", ++int_ptr); /* it will have advance by four bytes */  

    return 0; 
} 

我有我的机器上输出如下:

$ ./a.out 
0xbf8b85d2, 0xbf8b85d2, 0xbf8b85d2 
0xbf8b85d3 
0xbf8b85d6 

正如你可以看到,我们预测他们确实前进。这很明显,当我们开始解引用我们的指针并且它们不匹配底层类型时,这会引起各种各样的问题。

关于void*指针,arithmetic on them is illegal

0

这里的指针ptrc指的是数据类型为整数的变量的地址,但是您使用它的双精度值。