how can i get the address of buf which defined as char buf[] = "abcde";

C

Chris Torek

I don't think that what you mean by "value" "in quotes"
is very close to the meaning of value.

Indeed, this is why it is in quotes. The value of an ordinary
object is the value stored in the object. The "value" of an
array should therefore be the collection of all the values of
all the elements of that array.

This would require that C have "array rvalues", but with one weird
case (functions that return "struct"s that contain arrays), it does
not. Instead, it has The Rule.
In this kind of an array definition:
char array[] = "ab";
the expressions on both sides of the equal sign are array types.

Actually, the thing on the right is merely a special syntactic
construct, which the standard calls a "string literal". It does
*become* an array, but not as an expression, because initializers
for arrays of character types are another special case. (See
§6.1.4, paragraph 5, §6.2.2.1 para 3, and §6.5.8 paragraphs 17 and
18, at least in my C99 draft.)
 
J

Jens.Toerring

pete said:
Chris Torek wrote:
I don't think that what you mean by "value" "in quotes"
is very close to the meaning of value.

Take 'value' when put in quotes to mean "in a context where the
value of something is taken that doesn't really has a value".
Saying that an array has a value doesn't really make sense when
you think about it. But in C you can use an array in places where
a value is expected (like when you use an array as a function ar-
gument where the function expects a pointer or when you have a
pointer on the left hand side and an unadorned array on the right
of an assignment) anyway and then The Rule kicks in and the arrays
"value" is taken to mean the value of the pointer to it's first
element.
That an array should have the same "value" regardless
of it's contents or whether or not it's been initialized,
is too different from the meaning of value, for me.
The value of an object should depend on it's contents.

Well, define what 'value' of an array should mean. An array has no
single 'value' (except maybe for the degenerate case of an array
with only a single element). The guys that invented C decided to
pick the address of the first element as meaning the 'value' of the
array.
In this kind of an array definition:
char array[] = "ab";
the expressions on both sides of the equal sign are array types.

Definitions are extra tricky. And on the left hand side you actu-
ally don't have an array here but a pointer to a literal string.
The special magic rules for the initialization of char arrays allow
this and make sure that a) the array on the left hand side will
be made large enough to hold a copy of the literal string and
b) what the pointer to literal string points to gets copied to
the array. And such an assignment doesn't work when you try it
somewere else than an initialization, e.g.

char array[ 3 ];
array = "ab";

is a syntax error.
The initializing elements are derived from the contents of "ab",
or as I think of it, from the value of the array "ab".

Then you assign a different meaning to "value of an array" than it
has in C by definition. If things would work line this, then

int a[ 3 ] = { 1, 2, 3 };
int b[ 3 ];
b = a;

should probably be legal and would assign the values of the elements
of array 'a' to the ones of array 'b'. But I guess you will have pro-
blems getting your C compiler to create code for you that does that.
To make things more interesting, something like this works with e.g.
structures, even though you also can't say that a structure has a
value in the normal sense. So structures don't "decay" to a pointer
to the structure (or it's first member) in value context while arrays
do. C can sometimes be a little strange, admittedly;-)

Regards, Jens
 
B

baumann@pan

Chris said:
[Given:
char buf[N];
for some suitable constant N]

&buf[0] = buf = &buf is __TRUE__ only if we don't consider the data
type, but the value only.

If you "don't consider the data type", then 3 == 3.14, and 3 != 3.14.
we can cast the three to void * , a pointer.

We can cast the 3.14 to "long", and then 3 == 3.14.

Or, we can convert (via cast or via ordinary cast-free conversion)
the 3 to "double", and then 3 != 3.14.

This shows that:

IF YOU IGNORE THE TYPE, YOU GET THE WRONG ANSWER.

Never, ever, ignore the type. C is *not* a typeless language!
(void*)&buf[0] has the same value of (void*) &buf

Probably, and perhaps even provably. (It would be hard, and perhaps
impossible, to get the rest of the C Standard's requirements right
while also doing something weird with array addressing that would,
say, encode the size of the array in the result of (void *)&buf,
so that it differs from (void *)&buf[0].) But this just means
that:

If you take value A, of type T1, and value B, of type T2,
and convert both to new values of type T3, the new values
compare equal.

This is also true for (int)3 and (double)3.14. Value A has type
int, value B has type double, and we convert both to new values of
type "char", "short", "int", or "long" -- we have lots of choices
for type T3 -- and they will compare equal.
and same value of (void*)buf.

Yes; this falls out from The Rule about pointers and arrays in C
(<http://web.torek.net/torek/c/expr.html#therule>). The "value"
of an array object is a pointer to the array's first element.
Hence:

&buf[0] == buf

is always true -- no casts are required.
you all should notice

char * buf2 = (char*)mallic(100);

in this case we can get the address of buf2 by &buf2;

Yes. "buf2" is an object of type "pointer to char", so &buf2 is
a value of type "pointer to (pointer to char)", pointing to the
object named buf2.
but not &buf;

Here, "buf" is an object of type "array N of T", so &buf is a
value of type "pointer to (array N of T)", pointing to the
(entire) object name buf.
buf is same as buf2 which pointer to the location where the object
lies.

No! Learning this is crucial to becoming a fully competent C
programmer: buf is *not* "the same as" buf2. The object named
"buf" is an array. The object named "buf2" is not an array.
The rules for computing their values therefore differ. The
results of &buf and &buf2 differ. The results of sizeof(buf)
and sizeof(buf2) differ.

the result *buf and *buf2 is the same, but not *buf++ which i think
buf is constant , can not be modified , and *buf2++.


i think &buf is the address of buf according to the fact,

if we define a local variable in a func body.

most compiler generate asm code like

push ebp
mov ebp, esp
sub esp, NNN

then the buf 's value would in the range from ebp-n to ebp,this also is
the address of buf.
The thing that is peculiar is that the *different* rules for
computing the "value" of buf and the value of buf2 can cause
these two different things to have the same value! That is,
after:

char buf[N]; /* for some suitable N */
char *buf2;

buf2 = buf;

the values equal, but the entities differ. The values are equal
because the "value" of an array object is that produced by The Rule
about arrays and pointers in C.

printf("buf = %p, buf2 = %p; but sizeof(buf) = %lu, sizeof(buf2) = %lu\n",
(void *)buf, (void *)buf2,
(unsigned long)sizeof buf, (unsigned long)sizeof buf2);

The different "sizeof" results proves that the two are not identical.
This is why The Rule says: "in a value context". Some operations
-- in particular, unary "&" and sizeof -- are not "value contexts".
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
 
K

Keith Thompson

Take 'value' when put in quotes to mean "in a context where the
value of something is taken that doesn't really has a value".
Saying that an array has a value doesn't really make sense when
you think about it.

I disagree. A struct has a composite value, consisting of the values
of its members. An array has a composite value, consisting of the
values of its elements. I've used languages where arrays values can
be assigned and even compared using the same syntax that's used for
scalars. It's really no more strange than saying than a complex
number has a value.

Of course, C rarely lets you do anything with an array "value", but it
still exists.
 
B

baumann@pan

Chris said:
[Given:
char buf[N];
for some suitable constant N]

&buf[0] = buf = &buf is __TRUE__ only if we don't consider the data
type, but the value only.

If you "don't consider the data type", then 3 == 3.14, and 3 != 3.14.

&buf is a pointer to something,

buf in this case can also be considered as pointer , right?

since they are both pointer, they will occupy 32bits in 32-bit cpu.

so i can compare the 2 32-bit values.

no 3 == 3.14 would occur.


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


int main(void)
{
char buf[] = "abcdefghijklmn";
char *token = "l";
char *text = buf;
char * d = (char*)malloc(100);

char * p = strsep((char**)&text,token);
printf("d:%p\t &d:%p\n",d, &d);
printf("buf:%p,&buf:%p,&buf[0]:%p\n", buf, &buf,&buf[0]);
printf("p:%s\n",p);
free(d);
return 0;
}

compiled in redhat 9, outputs

d:0x80496c8 &d:0xbfffee04
buf:0xbfffee10,&buf:0xbfffee10,&buf[0]:0xbfffee10
p:abcdefghijk


you see buf &buf[0] and &buf have the same value:0xbfffee10.

so i mean the three in equal by value, what do you call this situation?

array is strange or exactly special thing ,i think, few variable of
other type and the address of them could be same ( i think it is mostly
because other type variable could not be taken as pointer , while
variable[] can be, so the comparision between the other type variable
and their address would have no meaning).





we can cast the three to void * , a pointer.

We can cast the 3.14 to "long", and then 3 == 3.14.

Or, we can convert (via cast or via ordinary cast-free conversion)
the 3 to "double", and then 3 != 3.14.

This shows that:

IF YOU IGNORE THE TYPE, YOU GET THE WRONG ANSWER.

Never, ever, ignore the type. C is *not* a typeless language!
(void*)&buf[0] has the same value of (void*) &buf

Probably, and perhaps even provably. (It would be hard, and perhaps
impossible, to get the rest of the C Standard's requirements right
while also doing something weird with array addressing that would,
say, encode the size of the array in the result of (void *)&buf,
so that it differs from (void *)&buf[0].) But this just means
that:

If you take value A, of type T1, and value B, of type T2,
and convert both to new values of type T3, the new values
compare equal.

This is also true for (int)3 and (double)3.14. Value A has type
int, value B has type double, and we convert both to new values of
type "char", "short", "int", or "long" -- we have lots of choices
for type T3 -- and they will compare equal.
and same value of (void*)buf.

Yes; this falls out from The Rule about pointers and arrays in C
(<http://web.torek.net/torek/c/expr.html#therule>). The "value"
of an array object is a pointer to the array's first element.
Hence:

&buf[0] == buf

is always true -- no casts are required.
you all should notice

char * buf2 = (char*)mallic(100);

in this case we can get the address of buf2 by &buf2;

Yes. "buf2" is an object of type "pointer to char", so &buf2 is
a value of type "pointer to (pointer to char)", pointing to the
object named buf2.
but not &buf;

Here, "buf" is an object of type "array N of T", so &buf is a
value of type "pointer to (array N of T)", pointing to the
(entire) object name buf.
buf is same as buf2 which pointer to the location where the object
lies.

No! Learning this is crucial to becoming a fully competent C
programmer: buf is *not* "the same as" buf2. The object named
"buf" is an array. The object named "buf2" is not an array.
The rules for computing their values therefore differ. The
results of &buf and &buf2 differ. The results of sizeof(buf)
and sizeof(buf2) differ.

The thing that is peculiar is that the *different* rules for
computing the "value" of buf and the value of buf2 can cause
these two different things to have the same value! That is,
after:

char buf[N]; /* for some suitable N */
char *buf2;

buf2 = buf;

the values equal, but the entities differ. The values are equal
because the "value" of an array object is that produced by The Rule
about arrays and pointers in C.

printf("buf = %p, buf2 = %p; but sizeof(buf) = %lu, sizeof(buf2) = %lu\n",
(void *)buf, (void *)buf2,
(unsigned long)sizeof buf, (unsigned long)sizeof buf2);

The different "sizeof" results proves that the two are not identical.
This is why The Rule says: "in a value context". Some operations
-- in particular, unary "&" and sizeof -- are not "value contexts".
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
 
P

pete

pete said:
Chris Torek wrote:
(<http://web.torek.net/torek/c/expr.html#therule>). The "value"
of an array object is a pointer to the array's first element.
In this kind of an array definition:
char array[] = "ab";
the expressions on both sides of the equal sign are array types.

Definitions are extra tricky. And on the left hand side you
actually don't have an array here but a pointer to a literal string.
The special magic rules for the initialization of char arrays allow
this and make sure that a) the array on the left hand side will
be made large enough to hold a copy of the literal string and
b) what the pointer to literal string points to gets copied to
the array. And such an assignment doesn't work when you try it
somewere else than an initialization, e.g.

There is no pointer there.

N869
6.3.2.1 Lvalues and function designators

[#3] Except when

it is the operand of the sizeof operator or
the unary & operator,

or is a string literal used to initialize an array,

an expression that has type ``array of
type'' is converted to an expression with type ``pointer to
type'' that points to the initial element of the array
object and is not an lvalue.
 
B

baumann@pan

pete said:
pete said:
Chris Torek wrote:
(<http://web.torek.net/torek/c/expr.html#therule>). The "value"
of an array object is a pointer to the array's first element.
In this kind of an array definition:
char array[] = "ab";
the expressions on both sides of the equal sign are array types.

Definitions are extra tricky. And on the left hand side you
actually don't have an array here but a pointer to a literal string.
The special magic rules for the initialization of char arrays allow
this and make sure that a) the array on the left hand side will
be made large enough to hold a copy of the literal string and
b) what the pointer to literal string points to gets copied to
the array. And such an assignment doesn't work when you try it
somewere else than an initialization, e.g.

There is no pointer there.

N869
6.3.2.1 Lvalues and function designators

[#3] Except when

it is the operand of the sizeof operator or

"operand of the sizeof"???
 
P

pete

Chris said:
Chris said:
(<http://web.torek.net/torek/c/expr.html#therule>). The "value"
of an array object is a pointer to the array's first element.
In this kind of an array definition:
char array[] = "ab";
the expressions on both sides of the equal sign are array types.

Actually, the thing on the right is merely a special syntactic
construct, which the standard calls a "string literal". It does
*become* an array, but not as an expression, because initializers
for arrays of character types are another special case. (See
§6.1.4, paragraph 5, §6.2.2.1 para 3, and §6.5.8 paragraphs 17 and
18, at least in my C99 draft.)

I can't find those numbers in N869.
Is there any text I can search for?

This part shown here, makes an exception for an
expression that has type ``array of type'',
refering to a string literal in an initialization.

N869
6.3.2.1 Lvalues and function designators

[#3] Except when

it is the operand of the sizeof operator or
the unary & operator,

or is a string literal used to initialize an array,

an expression that has type ``array of
type'' is converted to an expression with type ``pointer to
type'' that points to the initial element of the array
object and is not an lvalue.
 
P

pete

baumann@pan said:
Chris Torek wrote:

(<http://web.torek.net/torek/c/expr.html#therule>). The "value"
of an array object is a pointer to the array's first element.
In this kind of an array definition:
char array[] = "ab";
the expressions on both sides of the equal sign are array types.

Definitions are extra tricky. And on the left hand side you
actually don't have an array here
but a pointer to a literal string.
The special magic rules for the initialization
of char arrays allow
this and make sure that a) the array on the left hand side will
be made large enough to hold a copy of the literal string and
b) what the pointer to literal string points to gets copied to
the array. And such an assignment doesn't work when you try it
somewere else than an initialization, e.g.

There is no pointer there.

N869
6.3.2.1 Lvalues and function designators

[#3] Except when

it is the operand of the sizeof operator or

"operand of the sizeof"???
the unary & operator,

or is a string literal used to initialize an array,

an expression that has type ``array of
type'' is converted to an expression with type ``pointer to
type'' that points to the initial element of the array
object and is not an lvalue.


((sizeof "abcdef") == 7) is true
 
B

baumann@pan

what's N869?

and

when sizeof does not need () and when sizeof need ()? thanks

baumann@pan said:
(e-mail address removed)-berlin.de wrote:

Chris Torek wrote:

(<http://web.torek.net/torek/c/expr.html#therule>). The "value"
of an array object is a pointer to the array's first element.

In this kind of an array definition:
char array[] = "ab";
the expressions on both sides of the equal sign are array types.

Definitions are extra tricky. And on the left hand side you
actually don't have an array here
but a pointer to a literal string.
The special magic rules for the initialization
of char arrays allow
this and make sure that a) the array on the left hand side will
be made large enough to hold a copy of the literal string and
b) what the pointer to literal string points to gets copied to
the array. And such an assignment doesn't work when you try it
somewere else than an initialization, e.g.

There is no pointer there.

N869
6.3.2.1 Lvalues and function designators

[#3] Except when

it is the operand of the sizeof operator or

"operand of the sizeof"???
the unary & operator,

or is a string literal used to initialize an array,

an expression that has type ``array of
type'' is converted to an expression with type ``pointer to
type'' that points to the initial element of the array
object and is not an lvalue.


((sizeof "abcdef") == 7) is true
 
K

Keith Thompson

baumann@pan said:
Chris said:
[Given:
char buf[N];
for some suitable constant N]

&buf[0] = buf = &buf is __TRUE__ only if we don't consider the data
type, but the value only.

If you "don't consider the data type", then 3 == 3.14, and 3 != 3.14.

&buf is a pointer to something,

buf in this case can also be considered as pointer , right?

Sort of. buf is the name of an array object, but like any expression
of array type, it's implicitly converted (in most contexts) to a
pointer to its first element. In this case, &buf is of type pointer
to array of N chars, and buf (after the implicit conversion) is of
type pointer to char.
since they are both pointer, they will occupy 32bits in 32-bit cpu.

How do you know that? It happens to be true on many implementations,
but the standard doesn't guarantee it. In particular, it doesn't
guarantee that different pointer types are the same size. Whether
they're the same size or not, they're certainly different types.
so i can compare the 2 32-bit values.

Did you try it? In your program below, you print their values (but
incorrectly; read on), but you don't compare them.

You can have two 32-bit objects, both set to all-bits-zero, that
compare equal -- but if one of them is of type int and the other is of
type float, the fact that they compare equal is just happenstance.
They're of different types, just as the different pointers are of
different types.

Try this:

#include <stdio.h>
int main(void)
{
char buf[5];
if (buf == &buf) {
printf("They're equal\n");
}
else {
printf("They're not equal\n");
}
return 0;
}

When I compile this with gcc in strict mode, it prints "They're equal",
but only after issuing a diagnostic:

tmp.c:5: warning: comparison of distinct pointer types lacks a cast
no 3 == 3.14 would occur.


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


int main(void)
{
char buf[] = "abcdefghijklmn";
char *token = "l";
char *text = buf;
char * d = (char*)malloc(100);

char * p = strsep((char**)&text,token);
printf("d:%p\t &d:%p\n",d, &d);
printf("buf:%p,&buf:%p,&buf[0]:%p\n", buf, &buf,&buf[0]);
printf("p:%s\n",p);
free(d);
return 0;
}

compiled in redhat 9, outputs

d:0x80496c8 &d:0xbfffee04
buf:0xbfffee10,&buf:0xbfffee10,&buf[0]:0xbfffee10
p:abcdefghijk


you see buf &buf[0] and &buf have the same value:0xbfffee10.

so i mean the three in equal by value, what do you call this situation?

I call it undefined behavior. A printf with a "%p" format expects an
argument of type void*. If you give it a pointer to an array, it may
work as you expect, but the standard doesn't guarantee it.
array is strange or exactly special thing ,i think, few variable of
other type and the address of them could be same ( i think it is mostly
because other type variable could not be taken as pointer , while
variable[] can be, so the comparision between the other type variable
and their address would have no meaning).

What's special about arrays is that an array expression is implicitly
converted to a pointer to its first element (*not* a pointer to the
array) unless it's the operand of a unary "&" or sizeof operator.

Read section 6 of the C FAQ.
 
C

CBFalconer

baumann@pan said:
what's N869?

Haven't you learned not to top-post yet? See the reference marked
(C99) below. It is the last public draft of the C standard before
release.

--
Some useful references about C:
<http://www.ungerhu.com/jxh/clc.welcome.txt>
<http://www.eskimo.com/~scs/C-faq/top.html>
<http://benpfaff.org/writings/clc/off-topic.html>
<http://anubis.dkuug.dk/jtc1/sc22/wg14/www/docs/n869/> (C99)
<http://www.dinkumware.com/refxc.html> (C-library}
<http://gcc.gnu.org/onlinedocs/> (GNU docs)
 
S

schwarzb

baumann@pan said:
pete wrote:
(e-mail address removed) wrote:

hi all,

i want to get the address of buf, which defined as

char buf[] = "abcde";

so can call
strsep(address of buf, pointer to token);

The address of buf is &buf.

no, (&buf == buf )&&(buf == &buf[0]) is TRUE.

Without a cast, (&buf == buf) is undefined.

&buf is most definitely the address of buf.

no, buf ,&buf and &buf[0] is the address of "abcde", not address of
variable buf. i think we can not get the address of buf itself.

While all three expressions have the same value, the second has a
different type than the other two. It has type pointer to array of
char while the others have type pointer to char. Therefore, the
expression &buf == bug requires a diagnostic since there is no implicit
conversion between the two types.

Since buf is an array and not a pointer, all three expressions evaluate
to the address of the aggregate object buf.
 

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

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,165
Latest member
JavierBrak
Top