1

In the below program,

#include<stdio.h>
int main(){
  int a = 1025;
  int *p;
  p = &a;

  char *p0;
  p0 = (char *)p;


  //print("\n%d %d", *p0, *(p0+1));
  printf("\n%d and %d", *p0, p0[1]);

}

Output:

1 and 4


char & int are arithmetic types in C, To understand the output after type casting, I need to understand the binary representation of 1025, which is, 00000000 00000000 00000100 00000001. Little endianness of Intel arch will take first byte 00000001.

Question:

For the above program written in java, array notation cannot be used to access each byte of int.

In the above C program, array notation can be alternatively used to access each byte of int.

As per this program, How different is array from a pointer in C?

overexchange
  • 15,768
  • 30
  • 152
  • 347
  • 2
    An array is a contiguous sequence of elements. – Some programmer dude Oct 18 '16 at 12:22
  • @JoachimPileborg Same with one dimensional array in Java – overexchange Oct 18 '16 at 12:25
  • https://www.le.ac.uk/users/rjm1/cotter/page_59.htm – Abhineet Oct 18 '16 at 12:26
  • 7
    There is no array in your program. `p[x]` is just shorthand for `*(p + x)`. – Jabberwocky Oct 18 '16 at 12:27
  • The difference is that in your example you are telling the compiler that `p0` is pointing to a sequence of *`char`* (or bytes). As far as I know, something like this is not possible in Java. – Some programmer dude Oct 18 '16 at 12:27
  • @MichaelWalz Oh ok, got u. Thank you so much. – overexchange Oct 18 '16 at 12:27
  • @MichaelWalz Another question, [Comment](http://stackoverflow.com/questions/39965300/float-value-casted-to-char#comment67210927_39965300) contradicts my point in the query, How do you see this? – overexchange Oct 18 '16 at 12:34
  • 1
    @overexchange The comment you link describes casting of arithmetic values, not pointers. – Klas Lindbäck Oct 18 '16 at 12:37
  • 2
    "I need to understand the binary representation of 1025" The binary representation can as well be `00000001 00000100 00000000 00000000`. And that's actually what you have, since you got the output `1 4`. This is because of CPU endianess. – Lundin Oct 18 '16 at 12:41
  • @KlasLindbäck hmm? `int p=1025; char ch = (char)1025;`. Am claiming that, to know value of `ch`, I need to know the representation of `p`. Above program in query does indirectly using pointers. I know that any pointer type can be type casted to any other pointer type. – overexchange Oct 18 '16 at 12:41
  • If you have `int p=1025;`, then the result of `char ch = (char)p;` doesn't depend on endianess. `ch` will get the least significant byte, so you get `ch == 1`. However, `char ch = *((char*)&p);` will depend on endianess and `ch` will be either `1` or `0`. – Klas Lindbäck Oct 18 '16 at 13:06
  • @KlasLindbäck Correct!! You dont need to know endianness here, but I need to know the value sitting in the first byte of `int`(which is what I mean by representation). – overexchange Oct 18 '16 at 13:18
  • @MichaelWalz What was the idea for C authors to introduce such shorthand notation, which is confusin for new learners? – overexchange Oct 18 '16 at 13:20
  • @overexchange what confusion ? And tell me what is more readable and what is easier to write: `p[x]` or `*(p + x)` ? – Jabberwocky Oct 18 '16 at 13:23
  • @MichaelWalz `p[1]` is looks confusin, for a new learner mean, there is actual array in memory, where index 1 is being accessed from that array `p`. But `p` is not array of 4 bytes. – overexchange Oct 18 '16 at 13:57

4 Answers4

1

array - a contiguous series of elements that actually exists in memory. It has an address, usually considered as the address of the first element of the array.

pointer - a variable that contains an address. The address contained in a pointer may or may not point to actual memory.

Think of it this way - your home has an address. It exists somewhere, and you can put stuff in it - it's an array. You can put any address on an envelope and try to mail it. It may or may not get properly delivered for a lot of reasons - the street address written on an envelope is a pointer. And you can't store anything in that writing.

Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
0

For the above program written in java, array notation cannot be used to access each byte of int.

You're right

In the above C program, array notation can be alternatively used to access each byte of int.

Yes, you can declare a char pointer, point it to the first byte of the int and then access each byte of the int variable with array notation.

The same way you can declare an array

char arr[3]={1,2,3};

And use it as a pointer

char *prt;
prt = arr;

That is equivalent to

ptr = & ( arr[0] ); // The address of the first element of arr

As per this program, How different is array from a pointer in C?

To simplify (as per this program) an array is a pointer to the first element of the array.

p0 is a pointer to an array whose items are p0[0], p0[1],...

To clarify more:

You can declare a variable as a pointer or as array.

In your code you don't declare arrays.

But as you use p0[1] you're treating p0 as an array.

Finally:

I quote...

To understand the output after type casting

See https://stackoverflow.com/a/6752688/1579327

The result of casting a larger type into a smaller one is undefined (implementation dependent) iF the smaller type is signed and the value of the larger type doesn't fit into the smaller one.

Community
  • 1
  • 1
Paolo
  • 15,233
  • 27
  • 70
  • 91
  • What does it mean to say No? Can you share the java code? BTW, there is no array in the above query – overexchange Oct 18 '16 at 12:47
  • I meant "array notation cannot be used to access each byte of int" (edited the answer) – Paolo Oct 18 '16 at 12:50
  • What does *Yes* mean? Read what [Michael Walz](http://stackoverflow.com/questions/40108113/how-different-is-array-from-a-pointer-in-c#comment67487671_40108113) says. – overexchange Oct 18 '16 at 12:52
  • *Yes* means that what you stated is true. I tried to clarify more. See my last edit. – Paolo Oct 18 '16 at 13:00
0

Strictly answering the question in the title - arrays are not pointers:


  • int arr[10]:

    • Amount of memory used is sizeof(int)*10 bytes

    • The values of arr and &arr are necessarily identical

    • arr points to a valid memory address, but cannot be set to point to any other memory address (i.e., it serves as a constant "label")


  • int* ptr = malloc(sizeof(int)*10):

    • Amount of memory used is sizeof(int*) + sizeof(int)*10 bytes

    • The values of ptr and &ptr are not necessarily identical (in fact, they are mostly different)

    • ptr can be set to point to both valid and invalid memory addresses (i.e., you can change it during runtime as many times as you will)

barak manos
  • 29,648
  • 10
  • 62
  • 114
0

Even though they aren't the same thing, there is a close relationship between arrays and pointers in C. The array subscripting operation a[i] is defined in terms of pointer arithmetic:

a[i] == *(a + i)

That is, take the address a, offset i elements of the array's base type from that address, and dereference the result. For example, if a is an array of int, the expression a + 1 evaluates to the address of the next integer object following the one stored at a, which may be anywhere from 2, 4, or 8 bytes away.

Arrays are not pointers; however, except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element in the array.

So, given the code

int a[10];
a[2] = 2;

In the statement a[2] = 2, the expression a is not the operand of the sizeof or unary & operators, so it is converted ("decays") from type int [10] to int *, and it evaluates to the address of the first element of a. We then offset 2 elements of type int from that address and assign the value 2 to that location. Note that this conversion applies to the expression a, not the array object to which it refers.

So how does all that relate to your code?

In C, a non-bitfield object is composed of a contiguous sequence of one or more bytes. Objects of char type take up 1 byte by definition, so an object of any multibyte type (int, long, float, double, etc.) can be treated as an array of char (or unsigned char).

A picture may help - I took your code and used a little utility I wrote to dump the contents of each object in memory:

       Item        Address   00   01   02   03
       ----        -------   --   --   --   --
          a 0x7ffffa8a29cc   01   04   00   00    ....

          p 0x7ffffa8a29c0   cc   29   8a   fa    .)..
            0x7ffffa8a29c4   ff   7f   00   00    ....

         p0 0x7ffffa8a29b8   cc   29   8a   fa    .)..
            0x7ffffa8a29bc   ff   7f   00   00    ....

The binary representation of 1025 is 0x0401. As you can see, the object a is 4 bytes wide and contains the byte sequence {0x01, 0x04, 0x00, 0x00}. This is on an x86 system, which is little-endian, so the least significant byte comes first in the sequence.

Both p and p0 store the address of a. I'm on a 64-bit system, so pointer values are 8 bytes wide.

*p0 evaluates to the value of first byte in a, which in this case is 0x01. p0[1] is equivalent to *(p0 + 1), and evaluates to the value of the second character value following p0, which in this case is 0x04.

John Bode
  • 119,563
  • 19
  • 122
  • 198