pointer and array

J

Joona I Palaste

Leon Brodskiy said:
Could please anyone clarify about pointer and array in C?
If I have:
int arr[10];
The following two commands will be the same: arr and &arr[0].

They're expressions, not commands. But yes, they're the same thing,
in a value context.
What about &arr? Is it not the same thing?

Not the same thing at all. It's the address of the entire array, not
its first element. The most practical meaning of this is that such
addresses increment in terms of 10*sizeof(int), not in terms of
sizeof(int).
 
J

Joona I Palaste

Leon Brodskiy said:
Thanks for your answer.
I'm asking because I have found in a program the following call:
void f1(char inp[10])
{...}
void main()

Change this to int main(void).
{...
char str[10];
...
f1(&str);
...
}
I tought this is a bug and this is not supposed to work but it does work.
Function receives pointer to char. I send to the function a pointer to a
pointer to char but still seems like in arrays it is the same pointer. So,
is this case str and &str the same?

That program is *NOT* correct. You are supposed to call f1(str), not
f1(&str). If the function f1 assigns its parameter to a char pointer
(char*), it might work under your implementation. But trying to access
the char array pointer (char(*)[]) as if it were a char pointer will
yield wrong results, mainly for the reasons I stated.
 
J

Joona I Palaste

Joona I Palaste said:
Leon Brodskiy said:
Thanks for your answer.
I'm asking because I have found in a program the following call:
void f1(char inp[10])
{...}
void main()
Change this to int main(void).
{...
char str[10];
...
f1(&str);
...
}
I tought this is a bug and this is not supposed to work but it does work.
Function receives pointer to char. I send to the function a pointer to a
pointer to char but still seems like in arrays it is the same pointer. So,
is this case str and &str the same?
That program is *NOT* correct. You are supposed to call f1(str), not
f1(&str). If the function f1 assigns its parameter to a char pointer
(char*), it might work under your implementation. But trying to access
the char array pointer (char(*)[]) as if it were a char pointer will
yield wrong results, mainly for the reasons I stated.

I should not be answering C questions late in the evening. That program
is still wrong, but my answer above is wrong too. Any possible
assignment from &str to a char pointer happens *before* f1's code
begins, so what f1 does to the pointer does not matter. Does assigning
a char array pointer to a char pointer cause undefined behaviour?

--
/-- Joona Palaste ([email protected]) ------------- Finland --------\
\-------------------------------------------------------- rules! --------/
"Remember: There are only three kinds of people - those who can count and those
who can't."
- Vampyra
 
J

Joona I Palaste

Leon Brodskiy said:
If we leave char array pointer for a second, can we say that the program
will always work correctly?

No. The C standard allows for an implementation to behave erroneously
when a pointer value is assigned to a variable of incompatible type.
Would it be correct to say that a difference between str and &str is that
str is char* (points to one single character) and &str is a pointer to an
array(points to array of 10 characters)?
Yes.

If this is a true then in the
program should not be any difference if we use &str or str - both of them
will send to the function the address of the first element in the array.

That is not true in the general case. At least I think it's not. Maybe
some of the real C gurus here can answer my original question about
whether it is undefined behaviour?

--
/-- Joona Palaste ([email protected]) ------------- Finland --------\
\-------------------------------------------------------- rules! --------/
"Parthenogenetic procreation in humans will result in the founding of a new
religion."
- John Nordberg
 
K

Keith Thompson

Leon Brodskiy said:
If we leave char array pointer for a second, can we say that the program
will always work correctly?

Would it be correct to say that a difference between str and &str is that
str is char* (points to one single character) and &str is a pointer to an
array(points to array of 10 characters)? If this is a true then in the
program should not be any difference if we use &str or str - both of them
will send to the function the address of the first element in the array.

Please don't top-post. Your response should follow any quoted text,
not precede it.

No we can't say that the program will always work correctly. A
pointer-to-char and a pointer-to-array-of-char are two distinct types.
On most systems, they happen to have the same representation and can
be used more or less interchangeably, but the language standard
doesn't guarantee this.
 
L

Leon Brodskiy

Hi,

Could please anyone clarify about pointer and array in C?

If I have:

int arr[10];

The following two commands will be the same: arr and &arr[0].

What about &arr? Is it not the same thing?
 
I

infobahn

Leon said:
Thanks for your answer.
I'm asking because I have found in a program the following call:

void f1(char inp[10])
{...}

void main()

A simple mistake. You meant:

int main(void)
{...
char str[10];
....
f1(&str);

This should be f1(str);

&str is a char (*)[10], not a char *, so it has the wrong type
for the f1() function.
 
J

Joe Wright

Joona said:
No. The C standard allows for an implementation to behave erroneously
when a pointer value is assigned to a variable of incompatible type.




That is not true in the general case. At least I think it's not. Maybe
some of the real C gurus here can answer my original question about
whether it is undefined behaviour?

The two yield incompatible pointer types. I suppose a diagnostic is
required. I too await guru WRT undefined behavior.
 
L

Leon Brodskiy

Thanks for your answer.
I'm asking because I have found in a program the following call:

void f1(char inp[10])
{...}

void main()
{...
char str[10];
....
f1(&str);
....
}

I tought this is a bug and this is not supposed to work but it does work.
Function receives pointer to char. I send to the function a pointer to a
pointer to char but still seems like in arrays it is the same pointer. So,
is this case str and &str the same?

Thanks.

Joona I Palaste said:
Leon Brodskiy said:
Could please anyone clarify about pointer and array in C?
If I have:
int arr[10];
The following two commands will be the same: arr and &arr[0].

They're expressions, not commands. But yes, they're the same thing,
in a value context.
What about &arr? Is it not the same thing?

Not the same thing at all. It's the address of the entire array, not
its first element. The most practical meaning of this is that such
addresses increment in terms of 10*sizeof(int), not in terms of
sizeof(int).
 
B

Barry Schwarz

Thanks for your answer.
I'm asking because I have found in a program the following call:

void f1(char inp[10])
{...}

void main()
{...
char str[10];
...
f1(&str);

This requires a diagnostic. &str has type pointer to array of 10
char. f1 requires an argument of type pointer to char. These two
types are not compatible (implicit conversion between them is not
allowed). You need to up the warning level of your compiler so that
the required diagnostic is not suppressed.
...
}

I tought this is a bug and this is not supposed to work but it does work.
Function receives pointer to char. I send to the function a pointer to a
pointer to char but still seems like in arrays it is the same pointer. So,
is this case str and &str the same?

The expressions str and &str both evaluate to the same location in
memory but with different types. Apparently on your system, the two
types have the same representation so f1 is unaware you provided an
incorrect argument.

Passing an argument of the wrong type invokes undefined behavior. It
is your misfortune that this behavior takes the form of appearing to
work.




<<Remove the del for email>>
 
C

CBFalconer

Leon said:
If we leave char array pointer for a second, can we say that the
program will always work correctly?
.... snip ...

Please do not toppost in c.l.c. Your answer belongs after (or
interspersed with) the snipped material quoted, which the snippage
removing anything not germane to your reply.

In technical newsgroups top-posting is consider gauche, ignorant,
and rude.
 
D

Dave Vandervies

[str is an array]
The two yield incompatible pointer types. I suppose a diagnostic is
required. I too await guru WRT undefined behavior.

str has type "array of [I assume] char", which decays to "pointer to
char", pointing at the first char in the array.
&str has type "pointer to array of char", and points at (the beginning
of) the array; this happens to be the same memory location as the char
that the pointer that str decays to points at.

So, the types are different (and incompatible), but the values are
the same.

A diagnostic is required (because the types are incompatible). If the
compiler generates an executable anyways and if you ignore the diagnostic
and run the executable, you invoke undefined behavior.
If the two pointers have the same representation (a reasonable assumption
on a modern general-purpose processor like the one the OP is most likely
trying to run the code on), this particular undefined behavior is likely
to be "works as expected" (the compiler would have to go out of its way
to break it, since the values and the representations are the same).

A compiler for such an architecture invoked in "sorta-conforming
mode" could ignore the error. (Not issuing a diagnostic would make
it non-conforming, but that would probably be a Rather Small part of
its non-conformingness.) This doesn't mean the code isn't broken,
just that it's the kind of bug that has very strong survival instincts.
It won't come out and bite you until you're absolutely certain that
there's nothing wrong with that particular chunk of code, so you'll
waste your time and energy looking somewhere else.


dave
 
L

Leon Brodskiy

If we leave char array pointer for a second, can we say that the program
will always work correctly?

Would it be correct to say that a difference between str and &str is that
str is char* (points to one single character) and &str is a pointer to an
array(points to array of 10 characters)? If this is a true then in the
program should not be any difference if we use &str or str - both of them
will send to the function the address of the first element in the array.

Thanks in advance.

Joona I Palaste said:
Joona I Palaste said:
Leon Brodskiy said:
Thanks for your answer.
I'm asking because I have found in a program the following call:
void f1(char inp[10])
{...}
void main()
Change this to int main(void).
{...
char str[10];
...
f1(&str);
...
}
I tought this is a bug and this is not supposed to work but it does work.
Function receives pointer to char. I send to the function a pointer to a
pointer to char but still seems like in arrays it is the same pointer. So,
is this case str and &str the same?
That program is *NOT* correct. You are supposed to call f1(str), not
f1(&str). If the function f1 assigns its parameter to a char pointer
(char*), it might work under your implementation. But trying to access
the char array pointer (char(*)[]) as if it were a char pointer will
yield wrong results, mainly for the reasons I stated.

I should not be answering C questions late in the evening. That program
is still wrong, but my answer above is wrong too. Any possible
assignment from &str to a char pointer happens *before* f1's code
begins, so what f1 does to the pointer does not matter. Does assigning
a char array pointer to a char pointer cause undefined behaviour?

--
/-- Joona Palaste ([email protected]) ------------- Finland --------\
\-------------------------------------------------------- rules! --------/
"Remember: There are only three kinds of people - those who can count and those
who can't."
- Vampyra
 
C

Chris Torek

So, the types are different (and incompatible),
Definitely.

but the values are the same.

Well, yes; but also no. Because they have different types, it is
impossible to compare the values, at least not without help.

Consider a similar example, using "int" and "float" instead:

int i = 3;
float f = 3.14;

Are these equal? Let us find out:

% cat t.c
#include <stdio.h>

int equal(int a, int b) {
return a == b;
}

int main(void) {
int i = 3;
float f = 3.14;

if (equal(i, f))
printf("i and f are equal\n");
else
printf("i and f are not equal\n");
return 0;
}
% cc -o t -O -Wall -W -ansi -pedantic t.c
% ./t
i and f are equal
%

Well, there you go -- 3 is in fact the same value as 3.14.

Of course, this is complete nonsense; and if we change the equal()
function to take two "double" values, we find that 3 != 3.14.

So which is it? Is 3 equal to 3.14, or is 3 not equal to 3.14?
Ask anyone numerate and you will hear "they are not", but in C,
they are -- at least, sometimes. Before we can compare them,
we have to convert them to a common type, and the conversion
process can change the values. Converting a "float" 3.14 to an
"int" truncates it to 3, so 3 == 3; converting both to double
expands 3 to 3.0, and leaves 3.14 as something close to 3.14
(it becomes about 3.140000104904, on a typical machine today).

Note that this last item -- the fact that 3.14 is not exact, and
as a double, actually has some digits after four more zeros --
means that sometimes, even 3.14 is not equal to 3.14 (depending
on just what is behind those zeros):

% cat u.c
#include <stdio.h>

int equal(double a, double b) {
return a == b;
}

int main(void) {
float f = 3.14;

if (equal(f, 3.14))
printf("f is equal to 3.14\n");
else
printf("f is not equal to 3.14\n");
return 0;
}
% cc -o u -O -Wall -W -ansi -pedantic u.c
% ./u
f is not equal to 3.14
%

Clearly, we have to be careful with conversions -- they make
things that are obvious (like 3.14 == 3.14) turn out to be false,
sometimes.

The same holds for pointers. Given two differently-typed pointers,
we have to convert at least one of them, if not both, before we
can even compare them. If we have:

T1 *p1;
T2 *p2;

where T1 and T2 are different types, and we assign values to p1
and p2, and then convert them:

if (p1 == (T1 *)p2)

and this claims they are equal -- well, what if this is like the
int 3 and the float 3.14, that are equal when we convert them both
to int?

In some sense, this whole thing is not even an interesting question.
If the types differ, we should not be comparing the things in the
first place. But sometimes we want to do it anyway. In that case,
how do we convert them without screwing up the result?

The int-and-float case continues to be instructive. If we rewrite
equal() to take two "float"s, 3 != 3.14, and we do not have to
worry about 3.14 != 3.14. So this looks like a good idea. But
hang on: what happens if we compare (int)33554432 with (double)33554433.0?

I am not going to quote the C code here, but the trick is, I have
chosen an int that is too big for a "float" on my machine, so that
the "double" 33554433.0 becomes 33554432.0 after conversion to
float. This makes the numbers equal, when obviously they are not.
It turns out that "float" is *not* good enough as a common type,
for comparing int-and-double. The reason is that, while float
obviously preserves all float values, conversion to float irrecoverably
alters certain int values. Similarly, int is not good for comparing
either int-and-double or int-and-float, because conversion to int
alters many float or double values.

What we really need is a common type that *always* produces a
recoverable transformation. That is, given two values v1 and v2
of types T1 and T2 respectively, we need a type T3 where:

(T1)(T3)v1 == v1 /* i.e., (T3)v1 is recoverable */

and:

(T2)(T3)v2 == v2 /* (T3)v2 is also recoverable */

Given such a type, we can finally come up with a usable definition
of "is equal to": v1 is equal to v2 if (T3)v1 == (T3)v2. This
definition is (I claim) also consistent if, for every additional
type T4 for which the "recoverable transformation" property holds,
the "is equal to" relationship remains unchanged when using type
T4.

For data pointers in C, there is definitely such a type T3: the
"void *" type (which must use the same underlying representation
as "char *", which has consequences that are beyond the scope of
this newsgroup posting :) ) allows you to convert any valid value
from some other data-pointer type, to "void *", then back, and
always get a result that compares equal to the original pointer.

Is there a type T4 (other than "char *" with its same-representation
thing)? This is implementation-dependent. So we can define an
"is equal to" relationship using "void *", but we cannot say for
certain whether it is consistent.

Note that, as Dave Vandervies already said, this "is equal to"
definition does *not* mean "is compatible with": on some machines,
passing a "char *" where an "int *" is required (or vice versa)
will not work properly, even if the two pointer values are "equal"
under void-star conversions. In this particular case, I am not
even sure you can prove that &arr and &arr[0] are "void-star-equal".
(I think they *are* void-star-equal; I just have trouble proving
it!)
 
E

E. Robert Tisdale

Leon said:
Could please anyone clarify about pointer and array in C?

If I have:

int arr[10];

The following two commands will be the same: arr and &arr[0].

What about &arr? Is it not the same thing?
> cat main.c
#include <stdio.h>

int main(int argc, char* argv[]) {
int arr[10];
fprintf(stdout, "sizeof(arr) = %u\n", sizeof(arr));
fprintf(stdout, "sizeof(&arr[0]) = %u\n", sizeof(&arr[0]));
return 0;
}
> gcc -Wall -std=c99 -pedantic -o main main.c
> ./main
sizeof(arr) = 40
sizeof(&arr[0]) = 4

arr is the name of an array of 10 objects of type int.
&arr[0] is a pointer to the first object in that array.
 
L

Lawrence Kirby

No. The C standard allows for an implementation to behave erroneously
when a pointer value is assigned to a variable of incompatible type.

A compiler can refuse to compile the program, indeed this is a reasonable
thing for a compiler to do in this case.

No, the value of str is a pointer to the first element of the array, &str
is a pointer to the array as a whole. There is no requirement that these
two types of pointer have the same representation or are passed in the
same way in a function call. Often things happen to work, but that is not
the same thing as the source code being correct.
That is not true in the general case. At least I think it's not. Maybe
some of the real C gurus here can answer my original question about
whether it is undefined behaviour?

The program contains a constraint violation which means that it isn't a
valid C program. So issues like behaviour (from a C language
perspective) don't apply. OTOH since it isn't a valid C program a C
compiler can do what it likes with it after issuing the required
diagnostic. So from that perspective it is very much like undefined
behaviour.

Lawrence
 
B

Barry Schwarz

If we leave char array pointer for a second, can we say that the program
will always work correctly?

Would it be correct to say that a difference between str and &str is that
str is char* (points to one single character) and &str is a pointer to an
array(points to array of 10 characters)? If this is a true then in the
program should not be any difference if we use &str or str - both of them
will send to the function the address of the first element in the array.

It is not necessary for a pointer to char and a pointer to array of
char to have the same representation. They could even be of different
sizes or have different alignment requirements.


<<Remove the del for email>>
 
B

Barry Schwarz

Leon said:
Could please anyone clarify about pointer and array in C?

If I have:

int arr[10];

The following two commands will be the same: arr and &arr[0].

What about &arr? Is it not the same thing?
cat main.c
#include <stdio.h>

int main(int argc, char* argv[]) {
int arr[10];
fprintf(stdout, "sizeof(arr) = %u\n", sizeof(arr));

Since size_t need not be an unsigned int, a cast would be appropriate
here.
fprintf(stdout, "sizeof(&arr[0]) = %u\n", sizeof(&arr[0]));
return 0;
}
gcc -Wall -std=c99 -pedantic -o main main.c
./main
sizeof(arr) = 40
sizeof(&arr[0]) = 4

arr is the name of an array of 10 objects of type int.
&arr[0] is a pointer to the first object in that array.



<<Remove the del for email>>
 
E

Emmanuel Delahaye

Leon Brodskiy wrote on 19/12/04 :
Hi,

Could please anyone clarify about pointer and array in C?

If I have:

int arr[10];

The following two commands will be the same: arr and &arr[0].

These are not 'commands' They are 'expressions'.

'arr' is the name of the array. Because arr == arr + 0, it is also the
address of its first element (&arr[0] is a complicated way of writing
arr + 0).
What about &arr? Is it not the same thing?

No. It's the address of the array (same value), *but the type is
different*. Actually it has the 'int (*)[10]' type, and can be assigned
to a pointer of the same type:

int arr[10];

int (*p)[10] = &arr;

Is it useful or not is another question.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++
 
E

Emmanuel Delahaye

Leon Brodskiy wrote on 19/12/04 :
I'm asking because I have found in a program the following call:

void f1(char inp[10])
{...}

void main()
{...
char str[10];
...
f1(&str);
...
}

I tought this is a bug and this is not supposed to work but it does work.

It's a bug because the types are not the same. (A decent and well
configured compiler should yell on it). It 'works' because the value is
the same, but the '&' should be removed.
Function receives pointer to char. I send to the function a pointer to a
pointer to char<...>

Wrong. You have sent the address of a pointer to an array of 10 char.
Its type is 'char(*)[10]'.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,156
Messages
2,570,878
Members
47,413
Latest member
KeiraLight

Latest Threads

Top