Output of the printf(a,*a,**a) where a is of type int [][][]

Discussion in 'C Programming' started by Nikhil Bokare, Feb 4, 2008.

  1. #include<stdio.h>

    int main()
    {
    int a[3][3][3];
    printf("%d %d %d %d",a,*a,**a,&a);
    }

    I tried the above code and got the same value for a, *a , **a and &a.
    Can anyone please tell me the reason behind such a behavior?
     
    Nikhil Bokare, Feb 4, 2008
    #1
    1. Advertising

  2. In article <>,
    Nikhil Bokare <> wrote:

    >#include<stdio.h>


    >int main()
    >{
    > int a[3][3][3];
    > printf("%d %d %d %d",a,*a,**a,&a);
    >}


    >I tried the above code and got the same value for a, *a , **a and &a.
    >Can anyone please tell me the reason behind such a behavior?


    You should not be printing out pointers with a %d format. A
    pointer might (or might not) occupy more storage than an int,
    so if you use a %d format you might be printing out only part
    of the address of the pointer. It is not uncommon for pointers
    to be longer than int; it is more common for pointers to -happen-
    to be the same size as long, but that is not guaranteed.
    You can use a %p format to write out a pointer to void
    (so be sure to cast the pointer to (void *) in the argument list,
    as pointers to different types may have different sizes.)

    Also, you have specified that your main returns int and yet
    you have not returned any value from main(). That will work in C99
    but has undefined behaviour in C90.
    --
    "I will speculate that [...] applications [...] could actually see a
    performance boost for most users by going dual-core [...] because it
    is running the adware and spyware that [...] are otherwise slowing
    down the single CPU that user has today" -- Herb Sutter
     
    Walter Roberson, Feb 4, 2008
    #2
    1. Advertising

  3. Nikhil Bokare said:

    > #include<stdio.h>
    >
    > int main()
    > {
    > int a[3][3][3];
    > printf("%d %d %d %d",a,*a,**a,&a);
    > }
    >
    > I tried the above code and got the same value for a, *a , **a and &a.


    They can't have the same value, because they don't have the same type. a
    has type int[3][3][3], *a has type int[3][3], **a has type int[3], and &a
    has type (int *)[3][3][3]. None of these is type int, so %d is
    inappropriate as a format specifier (and indeed the behaviour if you do
    this is undefined). Since printf lacks format specifiers for the
    above-mentioned types, a conversion is required, and the most obvious way
    to do this is to cast to void *, which of course discards the type
    information, so when you correct your program to use casts-to-void* and %p
    instead of %d, you shouldn't necessarily expect to see different values.

    > Can anyone please tell me the reason behind such a behavior?


    Mu.

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -http://www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Feb 4, 2008
    #3
  4. Nikhil Bokare

    Ben Pfaff Guest

    Nikhil Bokare <> writes:

    > int main()
    > {
    > int a[3][3][3];
    > printf("%d %d %d %d",a,*a,**a,&a);


    You should use %p to print pointers. To be really correct, you
    should also cast all of these values to void *.

    > }
    >
    > I tried the above code and got the same value for a, *a , **a and &a.
    > Can anyone please tell me the reason behind such a behavior?


    All of those expressions point to the same byte. It's just in
    their types that they have some differences.
    --
    char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
    ={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6},*p
    =b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
    2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}
     
    Ben Pfaff, Feb 4, 2008
    #4
  5. Nikhil Bokare <> writes:
    > #include<stdio.h>
    >
    > int main()
    > {
    > int a[3][3][3];
    > printf("%d %d %d %d",a,*a,**a,&a);
    > }
    >
    > I tried the above code and got the same value for a, *a , **a and &a.
    > Can anyone please tell me the reason behind such a behavior?


    You're lucky (or unlucky) that the program worked at all. The "%d"
    format requires an argument of type int. If you give it anything
    else, you invoke undefined behavior. You're probably getting
    meaningful results on your implementation, but there are no guarantees.

    If you want to print a pointer value, use "%p" and convert the
    argument to void*.

    You should also terminate your output with a newline ("\n") and return
    a value from main(); "return 0;" is usually the right thing.

    Getting to what you're really asking about, you should read section 6
    of the comp.lang.c FAQ, <http://www.c-faq.com/>. If you're still
    confused after that, feel free to come back with more specific
    questions.

    --
    Keith Thompson (The_Other_Keith) <>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Feb 4, 2008
    #5
  6. Thanks for pointing out my mistakes.
    This is my edited program:

    #include<stdio.h>

    int main()
    {
    int a[3][3][3];
    printf("%p %p %p %p",a,*a,**a,&a);
    return 0;
    }

    Its still printing the same value for all of them. How does it happen??
     
    Nikhil Bokare, Feb 4, 2008
    #6
  7. Nikhil Bokare

    John Bode Guest

    On Feb 4, 1:46 pm, Nikhil Bokare <> wrote:
    > Thanks for pointing out my mistakes.
    > This is my edited program:
    >
    > #include<stdio.h>
    >
    > int main()
    > {
    > int a[3][3][3];
    > printf("%p %p %p %p",a,*a,**a,&a);
    > return 0;
    >
    > }
    >
    > Its still printing the same value for all of them. How does it happen??


    Because all of those expressions evaluate to the same location. The
    address of an array is the same as the address of the first element of
    the array. The *types* of each expression are different (int (*)[3]
    [3], int (*)[3], int *, and int (*)[3][3][3], respectively), but they
    all refer to the same location.
     
    John Bode, Feb 4, 2008
    #7
  8. Nikhil Bokare said:

    > Thanks for pointing out my mistakes.
    > This is my edited program:
    >
    > #include<stdio.h>
    >
    > int main()
    > {
    > int a[3][3][3];
    > printf("%p %p %p %p",a,*a,**a,&a);


    That line should be:

    printf("%p %p %p %p",(void *)a,(void *)*a,(void *)**a,(void *)&a);

    > return 0;
    > }
    >
    > Its still printing the same value for all of them. How does it happen??


    They have different types, as I explained before, so they have different
    values, as I explained before. The casts to void * are required, as I
    explained before. Because the casts to void * discard type information,
    the differences between the values are also being discarded.

    Here's a real world parallel question:

    "I used a GPS to find out the location of an oxygen atom, a water molecule,
    and a water spillage on a kitchen table, and the GPS gave the same
    location for all three. Why?"

    Obviously, these are three very different things. Equally obviously,
    there's no particular reason why they shouldn't be in precisely the same
    place.

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -http://www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Feb 4, 2008
    #8
  9. Richard Heathfield <> writes:
    > Nikhil Bokare said:
    >> #include<stdio.h>
    >>
    >> int main()
    >> {
    >> int a[3][3][3];
    >> printf("%d %d %d %d",a,*a,**a,&a);
    >> }
    >>
    >> I tried the above code and got the same value for a, *a , **a and &a.

    >
    > They can't have the same value, because they don't have the same type. a
    > has type int[3][3][3], *a has type int[3][3], **a has type int[3], and &a
    > has type (int *)[3][3][3]. None of these is type int, so %d is
    > inappropriate as a format specifier (and indeed the behaviour if you do
    > this is undefined). Since printf lacks format specifiers for the
    > above-mentioned types, a conversion is required, and the most obvious way
    > to do this is to cast to void *, which of course discards the type
    > information, so when you correct your program to use casts-to-void* and %p
    > instead of %d, you shouldn't necessarily expect to see different values.


    The object ``a'' has type int[3][3][3], but the expression ``a'', in
    this context, has type int(*)[3][3], or pointer to array 3 of array 3
    of int; that's the type of the argument that's being passed to printf.

    Similarly, the expression ``*a'' has type int(*)[3], the expression
    ``**a'' has type int*, and the expression ``&a'' has type
    int(*p)[3][3][3]. (I *think* I got all those right; someone will
    certainly correct me if I didn't.)

    Certainly none of these has type int, so "%d" is the wrong format.

    Here's my version of the OP's program, adding ***a to the mix:

    #include<stdio.h>

    int main(void)
    {
    int a[3][3][3] = {0};
    int (*b)[3][3] = a;
    int (*c)[3] = *a;
    int *d = **a;
    int e = ***a;
    int (*f)[3][3][3] = &a;

    printf("%p %p %p %d %p\n",
    (void*)b, (void*)c, (void*)d, e, (void*)f);
    return 0;
    }

    --
    Keith Thompson (The_Other_Keith) <>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Feb 4, 2008
    #9
  10. Nikhil Bokare wrote:
    >
    > Thanks for pointing out my mistakes.
    > This is my edited program:
    >
    > #include<stdio.h>
    >
    > int main()
    > {
    > int a[3][3][3];
    > printf("%p %p %p %p",a,*a,**a,&a);
    > return 0;
    > }
    >
    > Its still printing the same value for all of them. How does it happen??


    Given the definition of "a":

    int a[3][3][3];

    What do the following actually mean:

    a
    *a
    **a
    &a

    --
    +-------------------------+--------------------+-----------------------+
    | Kenneth J. Brody | www.hvcomputer.com | #include |
    | kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
    +-------------------------+--------------------+-----------------------+
    Don't e-mail me at: <mailto:>
     
    Kenneth Brody, Feb 4, 2008
    #10
  11. Nikhil Bokare <> writes:
    > Thanks for pointing out my mistakes.
    > This is my edited program:
    >
    > #include<stdio.h>
    >
    > int main()
    > {
    > int a[3][3][3];
    > printf("%p %p %p %p",a,*a,**a,&a);
    > return 0;
    > }
    >
    > Its still printing the same value for all of them. How does it happen??


    Read section 6 of the comp.lang.c FAQ.

    --
    Keith Thompson (The_Other_Keith) <>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Feb 4, 2008
    #11
  12. Nikhil Bokare

    CBFalconer Guest

    Nikhil Bokare wrote:
    >
    > #include<stdio.h>
    >
    > int main() {
    > int a[3][3][3];
    > printf("%d %d %d %d",a,*a,**a,&a);
    > }
    >
    > I tried the above code and got the same value for a, *a , **a and
    > &a. Can anyone please tell me the reason behind such a behavior?


    It's accurate. Any response is accurate when behaviour is
    undefined. Which is the result of lying to printf about the type
    of data passed to it.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.



    --
    Posted via a free Usenet account from http://www.teranews.com
     
    CBFalconer, Feb 4, 2008
    #12
  13. Nikhil Bokare

    CBFalconer Guest

    Nikhil Bokare wrote:
    >
    > Thanks for pointing out my mistakes. This is my edited program:
    >
    > #include <stdio.h>
    >
    > int main() {
    > int a[3][3][3];
    > printf("%p %p %p %p",a,*a,**a,&a);
    > return 0;
    > }
    >
    > Its still printing the same value for all of them. How does it
    > happen??


    Because you are still lying to printf and getting undefined
    behaviour. %p requires a void* parameter. I also fixed your
    #include statement.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.



    --
    Posted via a free Usenet account from http://www.teranews.com
     
    CBFalconer, Feb 4, 2008
    #13
  14. Keith Thompson said:

    <snip>

    > The object ``a'' has type int[3][3][3], but the expression ``a'', in
    > this context, has type int(*)[3][3], or pointer to array 3 of array 3
    > of int; that's the type of the argument that's being passed to printf.


    Good spot. (Duh@me.) Thanks, Keith.

    <snip>

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -http://www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Feb 4, 2008
    #14
  15. Nikhil Bokare

    Bartc Guest

    "Richard Heathfield" <> wrote in message
    news:...
    > Nikhil Bokare said:
    >
    >> #include<stdio.h>
    >>
    >> int main()
    >> {
    >> int a[3][3][3];
    >> printf("%d %d %d %d",a,*a,**a,&a);
    >> }
    >> I tried the above code and got the same value for a, *a , **a and &a.


    I can't get my head around these either:

    >a has type int[3][3][3]


    Yet you dereference a in your next statement, so a's type must be ref
    something.:

    > *a has type int[3][3]


    >**a has type int[3]


    And again, so it must have been ref ref something (to use Algol68 notation
    for a minute).

    >&a has type (int *)[3][3][3].


    Now that one's really got me: &a is a 3D array of ref int? I expected ref
    [3][3][3]int.

    An array name decomposes to a ref to the first element. Let's work from
    there. In A68 mode, the variable is:

    [3] [3] [3] int a /* array of array of array of int */

    'a' decomposes to a reference to the first element, ie. ref [3] [3] int.
    Does it decompose further, although it's not an array anymore? Assume it
    does: now it's ref ref [3] int, and once more: ref ref ref int.

    And that's just 'a'. *a would be ref ref int, and **a would be ref int, and
    ***a would be an int (although the OP didn't go that far).

    Now you say that **a has type int[3] (or [3]int) and I say **a is ref int.
    (Which figures: in int b[3] then b decomposes to ref int when used in an
    expression).

    If all this is correct, then it's also completely crazy. Typically an
    int[3][3][3] would involve no pointers apart from it's static address. Yet
    the ***a expression implies there are 3 levels of pointers to dereference!

    I suppose they are just there to balance the &&&a[0][0][0] that the array
    decomposition rules apply. And I guess *a really means a[0]. Now it almost
    starts to make sense. Almost.

    --
    Bart
     
    Bartc, Feb 5, 2008
    #15
  16. CBFalconer <> writes:
    > Nikhil Bokare wrote:
    >> Thanks for pointing out my mistakes. This is my edited program:
    >>
    >> #include <stdio.h>
    >>
    >> int main() {
    >> int a[3][3][3];
    >> printf("%p %p %p %p",a,*a,**a,&a);
    >> return 0;
    >> }
    >>
    >> Its still printing the same value for all of them. How does it
    >> happen??

    >
    > Because you are still lying to printf and getting undefined
    > behaviour. %p requires a void* parameter. I also fixed your
    > #include statement.


    It's true that the above program lies to printf and thereby invokes
    undefined behavior. It's also true that one possible consequence of
    this undefined behavior is to print the same value four times.

    But it's almost certainly *not* true that the program prints the same
    value four times *because* it invokes undefined behavior.

    In most implementations, the behavior of passing a pointer value of a
    type other than void* to printf with a "%p" is exactly the same as the
    behavior of passing the same pointer value converted to void*. That's
    not guaranteed by the standard, of course, but it's very common. In
    the above program with that correction (casting all printf arguments
    after the format string to void* -- oh, yes, and adding a trailing
    "\n"), I would still expect it to print the same value four times.
    I'm not sure whether it's even possible for a conforming
    implementation *not* to print the same value four times.

    Yes, the program exhibits undefined behavior, and yes, that absolutely
    should be fixed, but that doesn't actually explain the behavior, and
    there is another explanation. There's nothing wrong with pointing out
    the undefined behavior *and then* answering the original question.

    In other words, why does *this* program print the same value four
    times? (I changed the spaces to new-lines to make it easier to see
    that all for values are the same.)

    #include <stdio.h>
    int main(void)
    {
    int a[3][3][3];
    printf("%p\n%p\n%p\n%p\n", (void*)a, (void*)*a, (void*)**a, (void*)&a);
    return 0;
    }

    (My answer to that is "Read section 6 of the comp.lang.c FAQ".)

    --
    Keith Thompson (The_Other_Keith) <>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Feb 5, 2008
    #16
  17. Nikhil Bokare

    CBFalconer Guest

    Keith Thompson wrote:
    >

    .... snip ...
    >
    > Yes, the program exhibits undefined behavior, and yes, that
    > absolutely should be fixed, but that doesn't actually explain
    > the behavior, and there is another explanation. There's
    > nothing wrong with pointing out the undefined behavior *and
    > then* answering the original question.


    Undefined behaviour can do _anything_. No explanation is needed.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.


    --
    Posted via a free Usenet account from http://www.teranews.com
     
    CBFalconer, Feb 5, 2008
    #17
  18. CBFalconer said:

    > Keith Thompson wrote:
    >>

    > ... snip ...
    >>
    >> Yes, the program exhibits undefined behavior, and yes, that
    >> absolutely should be fixed, but that doesn't actually explain
    >> the behavior, and there is another explanation. There's
    >> nothing wrong with pointing out the undefined behavior *and
    >> then* answering the original question.

    >
    > Undefined behaviour can do _anything_.


    Agreed, but there's nothing wrong with pointing out the undefined behaviour
    *and then* answering the original question.

    > No explanation is needed.


    The OP needed an explanation. The fact that his program was flawed does not
    change this.

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -http://www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Feb 5, 2008
    #18
  19. "Nikhil Bokare" <> wrote in message
    news:...
    > #include<stdio.h>
    >
    > int main()
    > {
    > int a[3][3][3];
    > printf("%d %d %d %d",a,*a,**a,&a);
    > }
    >
    > I tried the above code and got the same value for a, *a , **a and &a.
    > Can anyone please tell me the reason behind such a behavior?


    http://web.torek.net/torek/c/pa.html
     
    Ravishankar S, Feb 5, 2008
    #19
  20. CBFalconer <> writes:
    > Keith Thompson wrote:
    > ... snip ...
    >>
    >> Yes, the program exhibits undefined behavior, and yes, that
    >> absolutely should be fixed, but that doesn't actually explain
    >> the behavior, and there is another explanation. There's
    >> nothing wrong with pointing out the undefined behavior *and
    >> then* answering the original question.

    >
    > Undefined behaviour can do _anything_.


    True.

    > No explanation is needed.


    Nonsense. It was obvious from the beginning that the OP was
    attempting to print the values of a, *a, **a, and &a, and wanted to
    know why they all appeared to have the same value. He clearly did
    require an explanation (i.e., he came to us for help), and digging
    through the undefined behavior to get to what he was actually asking
    about was easy enough that several of us managed to do it.

    A C program can behave in arbitrarily obnoxious ways in the presence
    of undefined behavior. We don't have to do likewise.

    --
    Keith Thompson (The_Other_Keith) <>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Feb 5, 2008
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Schnoffos
    Replies:
    2
    Views:
    1,221
    Martien Verbruggen
    Jun 27, 2003
  2. Hal Styli
    Replies:
    14
    Views:
    1,648
    Old Wolf
    Jan 20, 2004
  3. arun
    Replies:
    8
    Views:
    460
    Dave Thompson
    Jul 31, 2006
  4. aling
    Replies:
    8
    Views:
    958
    Jim Langston
    Oct 20, 2005
  5. Replies:
    21
    Views:
    312
    Barry Schwarz
    Mar 5, 2014
Loading...

Share This Page