2

I'm a beginner at learning pointers. Here is my code. (Note: I'm still trying to get my head around pointers so my code won't be clean.)

#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 expected the following output:

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

But instead I get this:

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

Can someone help for the large number I got when printing the contents of C? Why don't I get 3.14? (The number is actually longer than that but it didn't fit into this textbox. :-))

Bobby
  • 213
  • 2
  • 7
  • 1
    I think you want a double pointer, not int. – Hunter McMillen Jun 24 '13 at 02:11
  • I have a feeling it's got something to do with the fact that the pointer `ptrc` is set to point to a `int` datatype, but in reality is pointing to a `double` data type. `int` is usually 4 bytes, `double` is 8 bytes. The pointer is looking at 4 bytes of information, though it would have to read all 8 to get the true value of the `double`. To 'fix' the problem, declare `ptrc` as a `double`. – brazilianldsjaguar Jun 24 '13 at 02:12
  • 3
    Most of the answers here are missing the point. The problem occurs because sizeof(double) > sizeof(int), causing bits in the floating point values mantissa to become truncated. – Richard J. Ross III Jun 24 '13 at 02:15
  • The compiler probably tried very hard to provide you information on what you were doing wrong here in the form of warnings and errors. If you're using gcc or clang, make sure that when you compile you use "-Wall -Werror" and you will find you learn a lot faster. – kfsone Jun 24 '13 at 02:47
  • The code you posted contains numerous constraint violations (aka errors), which are pointed out in the answers below. A pedantic C compiler will refuse to compile it. Your C compiler might accept it due to loose error checking and non-standard extensions, but it must issue diagnostic messages in any case. Ignoring such errors (even if the code compiled) is never a good idea. – AnT stands with Russia Jun 24 '13 at 03:52
  • @Richard J. Ross III: The problem occurs becuse code contains errors. If you replace `double` with `float`, which is typically the same size as `int`, the code still wont't output `3.14`. – AnT stands with Russia Jun 24 '13 at 03:53

7 Answers7

5

You are declaring ptra, ptrb and ptrc as pointers to ints. But the type of a pointer is based on what it points to, so it really should be:

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

In your specific case, your program is trying to interpret a double value through an int pointer. Since the sizes of these data types differ on your machine, some of the bits of the double get discarded and you end up with the strange number you're seeing.

This may not always happen the same way - the result of accessing something through the wrong type of pointer is not defined by the C language, but it still might compile. C programmers refer to this as undefined behaviour (a phrase you should really come to terms with if you want to learn C!).

There is also the fact that when you call printf, you need to give it variables of the type it expects from the format string. So if you give it a format string where the first placeholder is %.f, you must give it a first argument that's a double. If you don't, printf will also exhibit undefined behaviour and could do anything (the undefined behaviour may be strange output, crashing, or simply putting out the number you expect... until the worst possible moment).

detly
  • 29,332
  • 18
  • 93
  • 152
  • Thanks. When you refer to undefined behaviour do you mean there is no way in the world of predicting what it will output? – Bobby Jun 24 '13 at 02:18
  • @Bobby: It’s not that there is no way to predict the behaviour; it’s that the standard doesn’t specify a behaviour, so the program is “ill-formed” and the compiler is free to do anything—and not document what it will do. – Jon Purdy Jun 24 '13 at 02:21
  • 1
    @Bobby - well... sort of. It's more that you *shouldn't* try to predict what will happen. If you know enough about your specific compiler and the machine your program will run on, you can usually say what's going to happen. But that's a fool's game, and you should stick to portable code. – detly Jun 24 '13 at 02:21
  • @Bobby - just some additional info: Most compilers have flags to warn about common kinds of undefined behaviour; for example `gcc` has `-Wall` and `clang` has `-fcatch-undefined-behaviour`. But these can only attempt to find a certain subset of undefined behaviour, and they're never going to be perfect. The best defense is to learn the language well, and when you ask a question about strange behaviour, look for answers that cite the C standard. – detly Jun 24 '13 at 02:39
2

Your pointers are all of type int. That is not correct. Replace those by

int *ptra;
char *ptrb;
double *ptrc;
unxnut
  • 8,509
  • 3
  • 27
  • 41
2

Because your pointers are all int*. If you want it to dereference to a double, you need it to be double*. Your compiler should have warned you about incompatible pointer assignment.

paddy
  • 60,864
  • 6
  • 61
  • 103
1

You should declare pointers using the corresponding type.

int *ptra;
char *ptrb;
double *ptrc;
jh314
  • 27,144
  • 16
  • 62
  • 82
1

you need to change your pointer type to match your data type so the size will be set accordingly.

char *ptrb;
double *ptrc;
DevZer0
  • 13,433
  • 7
  • 27
  • 51
0

If I can just say a few words about typed pointers.

Pointers with a type (as opposed to void* pointers) know how many bytes to advance in memory. For example on 32 bit systems and integer pointer would typically advance four bytes in memory when iterating through an array containing integer values.

A char pointer (guaranteed by the C standard to be always 1 byte) would naturally advance 1 byte at a time.

Let me illustrate this with a small code snippet:

#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;
}

I have the following output on my machine:

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

As you can see they have indeed advanced as we predicted. It is fairly obvious this can cause all sorts of problems when we start dereferencing our pointers and they don't match the underlying type.

Regarding void* pointers, arithmetic on them is illegal.

Community
  • 1
  • 1
Nobilis
  • 7,310
  • 1
  • 33
  • 67
0

here the pointer ptrc is referring to the addressof varaible whose data type is integer but you are using it for double.

pallavi
  • 114
  • 1
  • 3
  • 9