473,402 Members | 2,055 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,402 software developers and data experts.

Explain why this prints the same

Hello, I'm trying to help someone on a linux-oriented forum. I've taken
his original code and cleaned it up, but I am still wondering about
something. Here's the code:

#include <stdio.h>

int
main(void)
{
int a[][3]={ {1,2,3},{4,5,6,},{7,8,9} };
int *b = (int *)a;
int **c = (int **)a;
int i = 0;
int num_elements = sizeof(a) / sizeof(int);

for(i = 0; i< num_elements; ++i)
printf("*b = %d *c = %d\n", *b++, *c++);

return 0;
}

When compiled I get:
gcc -Wall -W -ansi -pedantic -g -O0 -c -o pointer_wonder.o
pointer_wonder.c
pointer_wonder.c: In function `main':
pointer_wonder.c:13: warning: int format, pointer arg (arg 3)
gcc pointer_wonder.o -o pointer_wonder.exe

The output is:
*b = 1 *c = 1
*b = 2 *c = 2
*b = 3 *c = 3
*b = 4 *c = 4
*b = 5 *c = 5
*b = 6 *c = 6
*b = 7 *c = 7
*b = 8 *c = 8
*b = 9 *c = 9

Why is it same for *b and *c?

/ Eric

Dec 7 '05 #1
12 1223

"Eric Lilja" <mi********@gmail.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...
Hello, I'm trying to help someone on a linux-oriented forum. I've taken
his original code and cleaned it up, but I am still wondering about
something. Here's the code:

#include <stdio.h>

int
main(void)
{
int a[][3]={ {1,2,3},{4,5,6,},{7,8,9} };
int *b = (int *)a;
int **c = (int **)a;
int i = 0;
int num_elements = sizeof(a) / sizeof(int);

for(i = 0; i< num_elements; ++i)
printf("*b = %d *c = %d\n", *b++, *c++);

return 0;
}

When compiled I get:
gcc -Wall -W -ansi -pedantic -g -O0 -c -o pointer_wonder.o
pointer_wonder.c
pointer_wonder.c: In function `main':
pointer_wonder.c:13: warning: int format, pointer arg (arg 3)
gcc pointer_wonder.o -o pointer_wonder.exe

The output is:
*b = 1 *c = 1
*b = 2 *c = 2
*b = 3 *c = 3
*b = 4 *c = 4
*b = 5 *c = 5
*b = 6 *c = 6
*b = 7 *c = 7
*b = 8 *c = 8
*b = 9 *c = 9

Why is it same for *b and *c?


*b gives you back an int

whereas

*c gives you back an int *

However, the 'values' of each are taken from a.

So, printf would really like a %p (at least) for the third arg.

Dec 7 '05 #2

"pemo" <us***********@gmail.com> wrote in message
news:dn**********@news.ox.ac.uk...

"Eric Lilja" <mi********@gmail.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...
Hello, I'm trying to help someone on a linux-oriented forum. I've taken
his original code and cleaned it up, but I am still wondering about
something. Here's the code:

#include <stdio.h>

int
main(void)
{
int a[][3]={ {1,2,3},{4,5,6,},{7,8,9} };
int *b = (int *)a;
int **c = (int **)a;
int i = 0;
int num_elements = sizeof(a) / sizeof(int);

for(i = 0; i< num_elements; ++i)
printf("*b = %d *c = %d\n", *b++, *c++);

return 0;
}

When compiled I get:
gcc -Wall -W -ansi -pedantic -g -O0 -c -o pointer_wonder.o
pointer_wonder.c
pointer_wonder.c: In function `main':
pointer_wonder.c:13: warning: int format, pointer arg (arg 3)
gcc pointer_wonder.o -o pointer_wonder.exe

The output is:
*b = 1 *c = 1
*b = 2 *c = 2
*b = 3 *c = 3
*b = 4 *c = 4
*b = 5 *c = 5
*b = 6 *c = 6
*b = 7 *c = 7
*b = 8 *c = 8
*b = 9 *c = 9

Why is it same for *b and *c?


*b gives you back an int

whereas

*c gives you back an int *

However, the 'values' of each are taken from a.

So, printf would really like a %p (at least) for the third arg.


So, [I should have added] *c's value is 1, 2, 3, ... where c is an int *
(obviously, you wouldn't want to deref that!

Dec 7 '05 #3
pemo wrote:

"Eric Lilja" <mi********@gmail.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...
Hello, I'm trying to help someone on a linux-oriented forum. I've taken
his original code and cleaned it up, but I am still wondering about
something. Here's the code:

#include <stdio.h>

int
main(void)
{
int a[][3]={ {1,2,3},{4,5,6,},{7,8,9} };
int *b = (int *)a;
int **c = (int **)a;
int i = 0;
int num_elements = sizeof(a) / sizeof(int);

for(i = 0; i< num_elements; ++i)
printf("*b = %d *c = %d\n", *b++, *c++);

return 0;
}

When compiled I get:
gcc -Wall -W -ansi -pedantic -g -O0 -c -o pointer_wonder.o
pointer_wonder.c
pointer_wonder.c: In function `main':
pointer_wonder.c:13: warning: int format, pointer arg (arg 3)
Note the warning here. ("*c++" is an "int*" type.)
gcc pointer_wonder.o -o pointer_wonder.exe

The output is:
*b = 1 *c = 1 [...] *b = 9 *c = 9

Why is it same for *b and *c?
*b gives you back an int

whereas

*c gives you back an int *

However, the 'values' of each are taken from a.


And it happens to be that sizeof(int)==sizeof(int*). Try it on a
system where this is not true, such as an old 16-bit DOS compiler
in large model mode. (sizeof int == 2, and sizeof int* is 4.)

In a test here, I get:

*b = 1 *c = 1
*b = 2 *c = 3
*b = 3 *c = 5
*b = 4 *c = 7
*b = 5 *c = 9
*b = 6 *c = 2013
*b = 7 *c = 2013
*b = 8 *c = 9
*b = 9 *c = 2680
So, printf would really like a %p (at least) for the third arg.


Though it would still print (basically) the same thing, as *c is
still really an int being treated as int*.
In any case, this probably falls under the "UB" heading, as you are
taking int's and treating them as int*'s.

(Yes, I know the apostrophes don't really belong in the last sentence,
but it makes it more legible, IMHO.)
--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>

Dec 7 '05 #4

"Kenneth Brody" <ke******@spamcop.net> wrote in message
news:43***************@spamcop.net...
pemo wrote:

"Eric Lilja" <mi********@gmail.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...
> Hello, I'm trying to help someone on a linux-oriented forum. I've taken
> his original code and cleaned it up, but I am still wondering about
> something. Here's the code:
>
> #include <stdio.h>
>
> int
> main(void)
> {
> int a[][3]={ {1,2,3},{4,5,6,},{7,8,9} };
> int *b = (int *)a;
> int **c = (int **)a;
> int i = 0;
> int num_elements = sizeof(a) / sizeof(int);
>
> for(i = 0; i< num_elements; ++i)
> printf("*b = %d *c = %d\n", *b++, *c++);
>
> return 0;
> }
>
> When compiled I get:
> gcc -Wall -W -ansi -pedantic -g -O0 -c -o pointer_wonder.o
> pointer_wonder.c
> pointer_wonder.c: In function `main':
> pointer_wonder.c:13: warning: int format, pointer arg (arg 3)
Note the warning here. ("*c++" is an "int*" type.)
> gcc pointer_wonder.o -o pointer_wonder.exe
>
> The output is:
> *b = 1 *c = 1 [...] > *b = 9 *c = 9
>
> Why is it same for *b and *c?


*b gives you back an int

whereas

*c gives you back an int *

However, the 'values' of each are taken from a.


And it happens to be that sizeof(int)==sizeof(int*). Try it on a
system where this is not true, such as an old 16-bit DOS compiler
in large model mode. (sizeof int == 2, and sizeof int* is 4.)

In a test here, I get:

*b = 1 *c = 1
*b = 2 *c = 3
*b = 3 *c = 5
*b = 4 *c = 7
*b = 5 *c = 9
*b = 6 *c = 2013
*b = 7 *c = 2013
*b = 8 *c = 9
*b = 9 *c = 2680
So, printf would really like a %p (at least) for the third arg.


Though it would still print (basically) the same thing, as *c is
still really an int being treated as int*.
In any case, this probably falls under the "UB" heading, as you are
taking int's and treating them as int*'s.

(Yes, I know the apostrophes don't really belong in the last sentence,
but it makes it more legible, IMHO.)


That's so cool!

I really should *invest* in an 'old' compiler! And, it'd be so great to
have a 'Take me Back' experience of my own [in an archive.org kinda sense].
Like, if only I'd saved some of programs I 'cut' into 7-hole punched tape (I
never had access to the punched cards!: they were [for eyes only] in the
domain of the machine room ops!)

I used to have my first Ph.D. thesis on one of those removable hard drives -
big clunky things, with equaly big handles!

Ok, I'm 48 - anyone care to beat that?

Old Fart
Dec 7 '05 #5
Eric Lilja wrote:

Hello, I'm trying to help someone on a linux-oriented forum. I've taken
his original code and cleaned it up, but I am still wondering about
something. Here's the code:

#include <stdio.h>

int
main(void)
{
int a[][3]={ {1,2,3},{4,5,6,},{7,8,9} };
int *b = (int *)a;
int **c = (int **)a;
int i = 0;
int num_elements = sizeof(a) / sizeof(int);

for(i = 0; i< num_elements; ++i)
printf("*b = %d *c = %d\n", *b++, *c++);

return 0;
}


I know this is going to be hard to believe,
but the standard doesn't actually define stepping all
the way through a two dimensional array
with anything other than a pointer to a character type,
even though all the bytes of array object are contiguous.

/* BEGIN new.c */

#include <stdio.h>

int
main(void)
{
char a[][3]={ "123","456","789" };
char *b = a[0];
size_t i = 0;
size_t num_elements = sizeof(a) / sizeof **a;

for(i = 0; i< num_elements; ++i) {
printf("*b = %c\n", *b++);
}
return 0;
}

/* END new.c */
--
pete
Dec 8 '05 #6
In article <11**********************@f14g2000cwb.googlegroups .com> "Eric Lilja" <mi********@gmail.com> writes:
Hello, I'm trying to help someone on a linux-oriented forum. I've taken
his original code and cleaned it up, but I am still wondering about
something. Here's the code:
Ok, let's see:
#include <stdio.h>

int
main(void)
{
int a[][3]={ {1,2,3},{4,5,6,},{7,8,9} };
Well, for a a segment of 9 integers is allocated succesively filled with
the integers 1 to 9.
int *b = (int *)a;
As 'a' in this context is a pointer to an array of three ints, you are
lying to the compiler. The result is (I think) undefined behaviour.
int **c = (int **)a;
And more so. Here the result is certain to be undefined behaviour.
int i = 0;
int num_elements = sizeof(a) / sizeof(int);

for(i = 0; i< num_elements; ++i)
printf("*b = %d *c = %d\n", *b++, *c++);
And this is the third time you are lying. You are lucky that
sizeof(int) == sizeof(*int) on your system.
return 0;
} .... The output is:
*b = 1 *c = 1 .... *b = 9 *c = 9

Why is it same for *b and *c?


Because on your system sizeof(int) == sizeof(*int) and the compiler
disregards all those lies.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Dec 8 '05 #7
pete wrote:

Eric Lilja wrote:

Hello, I'm trying to help someone on a linux-oriented forum. I've taken
his original code and cleaned it up, but I am still wondering about
something. Here's the code:

#include <stdio.h>

int
main(void)
{
int a[][3]={ {1,2,3},{4,5,6,},{7,8,9} };
int *b = (int *)a;
int **c = (int **)a;
int i = 0;
int num_elements = sizeof(a) / sizeof(int);

for(i = 0; i< num_elements; ++i)
printf("*b = %d *c = %d\n", *b++, *c++);

return 0;
}


I know this is going to be hard to believe,
but the standard doesn't actually define stepping all
the way through a two dimensional array
with anything other than a pointer to a character type,
even though all the bytes of array object are contiguous.


Unless you're treating it as a one dimensional array
of an array type.

/* BEGIN new.c */

#include <stdio.h>
#include <string.h>

int main(void)
{
char a[][3]={ "123","456","789" };
char *b = a[0];
char c[3][4] = {0};
char (*d)[3] = a;
char (*e)[4] = c;
size_t i;
size_t num_elements = sizeof(a) / sizeof **a;

for(i = 0; i< num_elements; ++i) {
printf("*b = %c\n", *b++);
}
putchar('\n');
num_elements = sizeof a / sizeof *a;
for(i = 0; i != num_elements; ++i) {
memcpy(e, d, sizeof *d);
printf("*e = %s\n", *e);
++d;
++e;
}
return 0;
}

/* END new.c */
--
pete
Dec 8 '05 #8
Dik T. Winter wrote:
"Eric Lilja" <mi********@gmail.com> writes:
#include <stdio.h>

int main(void) {
int a[][3]={ {1,2,3},{4,5,6,},{7,8,9} };

int *b = (int *)a;


As 'a' in this context is a pointer to an array of three ints, you are
lying to the compiler. The result is (I think) undefined behaviour.


I don't think there is any lying here; you are allowed to cast
one object pointer type to another as long as there are no
alignment issues. The troubles only (potentially) start when
you dereference the pointer.

&a[0] must be correctly aligned for int, because the members
of a[0] are ints, and there cannot be any padding before the
first member of an array.
int **c = (int **)a;

And more so. Here the result is certain to be undefined behaviour.


Here there could be alignment issues. But if there are not,
then no UB if c is not dereferenced.

(Note: I don't think I worded that exactly right -- the code always
has UB, but on implementations where there were no alignment
problems, the code would behave in a well-defined manner).
int i = 0;
int num_elements = sizeof(a) / sizeof(int);

for(i = 0; i< num_elements; ++i)
printf("*b = %d *c = %d\n", *b++, *c++);


And this is the third time you are lying. You are lucky that
sizeof(int) == sizeof(*int) on your system.


Agree (int* you mean, not *int).

IMHO, *b causes undefined behaviour iff i >= 3,
because "a" (ie. &a[0]) points to an array of 3 ints,
and a bounds checking implementation could flag this.

But if b were initialized as: int *b = &a;
then there would be no UB because &a points to
an object that is the size of nine ints.

But some people think that even as written there is
no UB because a[0] is part of the entire object "a",
I don't recall seeing any consensus when this point
has been debated in the past.

*c would cause undefined behaviour in most cases,
because either the bytes pointed to by c form a
trap representation for an int*, or if they form an address
that isn't the address of a valid object.

Dec 8 '05 #9
pemo wrote:
[...]
> main(void)
> {
> int a[][3]={ {1,2,3},{4,5,6,},{7,8,9} };
> int *b = (int *)a;
> int **c = (int **)a;
> int i = 0;
> int num_elements = sizeof(a) / sizeof(int);
>
> for(i = 0; i< num_elements; ++i)
> printf("*b = %d *c = %d\n", *b++, *c++);
>
> return 0;
> } [...] *c gives you back an int *

However, the 'values' of each are taken from a.
And it happens to be that sizeof(int)==sizeof(int*). Try it on a
system where this is not true, such as an old 16-bit DOS compiler
in large model mode. (sizeof int == 2, and sizeof int* is 4.)

In a test here, I get:

*b = 1 *c = 1 [...] *b = 9 *c = 2680

[...] That's so cool!

I really should *invest* in an 'old' compiler! And, it'd be so great to
have a 'Take me Back' experience of my own [in an archive.org kinda sense].
Like, if only I'd saved some of programs I 'cut' into 7-hole punched tape (I
never had access to the punched cards!: they were [for eyes only] in the
domain of the machine room ops!)
Well, you could probably find a very new compiler where
sizeof(int)!=sizeof(int*). I imagine that some of the 64-bit systems
might qualify.
I used to have my first Ph.D. thesis on one of those removable hard drives -
big clunky things, with equaly big handles!
You mean one of those washing machines that stored data?

That reminds me... My friend never returned my DEC-Tape with the copy
of Star Trek on it that he borrowed (mumble, mumble) years ago.
Ok, I'm 48 - anyone care to beat that?
Well, I'm "only" 44, but I do have 34+ years of programming experience.
Old Fart


--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>

Dec 8 '05 #10
pemo wrote:
"Kenneth Brody" <ke******@spamcop.net> wrote in message
And it happens to be that sizeof(int)==sizeof(int*). Try it on a
system where this is not true, such as an old 16-bit DOS compiler
in large model mode. (sizeof int == 2, and sizeof int* is 4.)


I really should *invest* in an 'old' compiler! And, it'd be so great to
have a 'Take me Back' experience of my own [in an archive.org kinda sense].


you could buy a new amd64 machine and experience the same pain today,
only faster. :)

Dec 8 '05 #11

"Kenneth Brody" <ke******@spamcop.net> wrote in message
news:43***************@spamcop.net...

<snip>
I used to have my first Ph.D. thesis on one of those removable hard
drives -
big clunky things, with equaly big handles!


You mean one of those washing machines that stored data?

That reminds me... My friend never returned my DEC-Tape with the copy
of Star Trek on it that he borrowed (mumble, mumble) years ago.
Ok, I'm 48 - anyone care to beat that?


Well, I'm "only" 44, but I do have 34+ years of programming experience.


"And you tell that to young. people today and. they won't believe you!"

Yup, it was a bit 'top-loader like' if memory still serves.

You've been programming longer then. I started as an undergrad - back then,
there was no university in the UK that offered *just* a degree in computing,
so I did a mixed degree, Computing and Pure Maths. Note the lack of the
term 'Computer Science' - wasn't really invented yet.

All my programming assignments had to be written out on coding sheets, and
handed into the machine room - where someone entered them, and probably
produced punched cards etc ... If you were unlucky, you'd turn up the next
day to get your printout, and find it said syntax error. Sometimes, it even
told you where! The *big* machine on which this stuff ran used to go on to
'MOP' at 6.00pm everyday. I don't believe I ever knew what MOP stood for,
but I know what it meant - the machine was hired out from 6.00 until
midnight every evening.

We did have one machine that we could program directly. A PDP ? In order to
use that, you had to enter the boot strap routine by flicking switches, and
then load the OS from seven hole punched tape.

Ah, those were the days!

Dec 9 '05 #12

"tedu" <tu@zeitbombe.org> wrote in message
news:11**********************@z14g2000cwz.googlegr oups.com...
pemo wrote:
"Kenneth Brody" <ke******@spamcop.net> wrote in message
> And it happens to be that sizeof(int)==sizeof(int*). Try it on a
> system where this is not true, such as an old 16-bit DOS compiler
> in large model mode. (sizeof int == 2, and sizeof int* is 4.)


I really should *invest* in an 'old' compiler! And, it'd be so great to
have a 'Take me Back' experience of my own [in an archive.org kinda
sense].


you could buy a new amd64 machine and experience the same pain today,
only faster. :)


:-)
Dec 9 '05 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Greg Stark | last post by:
This query is odd, it seems to be taking over a second according to my log_duration logs and according to psql's \timing numbers. However explain analyze says it's running in about a third of a...
5
by: J Allen Horner | last post by:
I'm just starting to learn C, and the tutorial I'm reading uses this code as an example: ----------- #include <stdio.h> #define MAX 10 int a; int rand_seed=10;
6
by: Mike Conklin | last post by:
This one really has me going. Probably something silly. I'm using dcount for a report to determine the number of different types of tests proctored in a semester. My report is based on a...
6
by: david epsom dot com dot au | last post by:
I have a report with an OLE bound frame. A bitmap has been pasted into the bound field. The bitmap displays and prints differently on different computers. In particular, the alignment is...
1
by: teddysnips | last post by:
Crystal Report problem - HELP! The fragments below come from two fundamentally identical applications. The one at the top - PrintEASAReport - throws an exception on the final line with the...
40
by: dev_cool | last post by:
hello everybody, i'm a new member of this group, this is my first ever post. i've found a c program that prints prime numbers through an infinite loop. But I really don't understand the code....
5
by: BlueJ | last post by:
Hi, I run the following source code: #include <stdio.h> main() { int i; unsigned int j;
4
by: kalar | last post by:
I want to draw a text on a JPanel.I know about method drawString but i can't make it work. Then i found a code in the Internet : learning java but i can't understand how works? If i put in...
9
by: tvnaidu | last post by:
This is just small plain HTML program wtote manually (since I am new to web programming, may be some tools I can use I think), this program loaded onto microcontroller with small foot print web...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.