473,804 Members | 3,004 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Rvalue of struct type

SRR
Consider the following code:
#include <stdio.h>
#include <string.h>
struct test{
char a[100];
}

funTest( void );
int main( void )
{
printf("%s",fun Test().a);
return 0;
}

struct test funTest()
{
struct test foo;
strcpy(foo.a,"H ello");
return foo;
}
In this I want to know how the following expression statement works:
printf("%s",fun Test().a);

funTest() is evaluated to yield an rvalue of type, "struct test" and
the expression "funTest(). a" yields an rvalue of type array of char,
which is converted to an rvalue equal to the pointer to the first
element of the char array and is passed to the printf() function.

My doubt is, since "funTest(). a" yields an rvalue of type, array of
char, how can it be converted to pointer type when we can have pointer
only for Lvalues and not for Rvalues.

Hope my question is clear.

Thanks in advance for the reply.

Mar 10 '07 #1
25 3504
SRR wrote:
Consider the following code:
#include <stdio.h>
#include <string.h>
struct test{
char a[100];
}

funTest( void );
While valid, this is really bad style. It looks like you forgot a
semicolon and expect funTest to return int, when you really do mean to
make funTest return struct test.
int main( void )
{
printf("%s",fun Test().a);
return 0;
}

struct test funTest()
{
struct test foo;
strcpy(foo.a,"H ello");
return foo;
}
In this I want to know how the following expression statement works:
printf("%s",fun Test().a);

funTest() is evaluated to yield an rvalue of type, "struct test" and
the expression "funTest(). a" yields an rvalue of type array of char,
which is converted to an rvalue equal to the pointer to the first
element of the char array and is passed to the printf() function.
Correct.
My doubt is, since "funTest(). a" yields an rvalue of type, array of
char, how can it be converted to pointer type when we can have pointer
only for Lvalues and not for Rvalues.
The pointer points to a temporary, and accessing that temporary after
the next sequence point, or modifying it, results in undefined
behaviour. (If you don't know what a sequence point is, please ask.)

char c = funTest().a[0]; /* valid, initialises c with 'H' */
char *p = funTest().a; /* valid, initialised p with a pointer value */
c = *p; /* invalid, accessing the function call's result after the
next sequence point */

funTest().a[0] = 'H'; /* invalid, modifying function call's result */

char str[100];
strcpy(str, funTest().a); /* invalid, accessing the function call's
result after the next sequence point */

Mar 10 '07 #2
SRR
On Mar 10, 2:51Â*pm, "Harald van Dijk" <true...@gmail. comwrote:
SRR wrote:
Consider the following code:
#include <stdio.h>
#include <string.h>
struct test{
Â* Â* Â* Â*char a[100];
}
funTest( void );

While valid, this is really bad style. It looks like you forgot a
semicolon and expect funTest to return int, when you really do mean to
make funTest return struct test.
Yes! You are right. But I did it inadvertantly while pasting the code.
Actually I typed it as
struct test{
char a[100];
}funTest( void );
Thanks for your comment abouy it.
>

int main( void )
{
Â* Â* printf("%s",fun Test().a);
Â* Â* return 0;
}
struct test funTest()
{
Â* Â* Â* Â*struct test foo;
Â* Â* Â* Â*strcpy(foo.a, "Hello");
Â* Â* Â* Â*return foo;
}
In this I want to know how the following expression statement works:
printf("%s",fun Test().a);
funTest() is evaluated to yield an rvalue of type, "struct test" and
the expression "funTest(). a" yields an rvalue of type array of char,
which is converted to an rvalue equal to the pointer to the first
element of the char array and is passed to the printf() function.

Correct.
My doubt is, since "funTest(). a" yields an rvalue of type, array of
char, how can it be converted to pointer type when we can have pointer
only for Lvalues and not for Rvalues.

The pointer points to a temporary, and accessing that temporary after
the next sequence point, or modifying it, results in undefined
behaviour. (If you don't know what a sequence point is, please ask.)
Thanks, I know the concept of Sequence Point. A function Call is a
sequence point as all the arguments are evaluated including all side
effects before entering the function.
Therefore my code produces undefined behavior as the temporary storage
may no longer contain the required data!
Now I understood why I got run time error when I compiled and executed
the code using Dev-CPP for Windows OS, but it executed well with
TurboCPP for MS-Dos.
Thanks once again for helping me understand what is really happening.
>
char c = funTest().a[0]; /* valid, initialises c with 'H' */
char *p = funTest().a; /* valid, initialised p with a pointer value */
c = *p; /* invalid, accessing the function call's result after the
next sequence point */

funTest().a[0] = 'H'; /* invalid, modifying function call's result */

char str[100];
strcpy(str, funTest().a); /* invalid, accessing the function call's
result after the next sequence point */- Hide quoted text -
Let us extend the topic. Is this the only case, when an rvalue of type
array is converted to rvalue of type pointer to the first element of
the array using temporary storage?
Any other possibility?
Thanks in advance for the reply.
- Show quoted text -

Mar 10 '07 #3
SRR
On Mar 10, 2:51Â*pm, "Harald van Dijk" <true...@gmail. comwrote:
SRR wrote:
Consider the following code:
#include <stdio.h>
#include <string.h>
struct test{
Â* Â* Â* Â*char a[100];
}
funTest( void );

While valid, this is really bad style. It looks like you forgot a
semicolon and expect funTest to return int, when you really do mean to
make funTest return struct test.


int main( void )
{
Â* Â* printf("%s",fun Test().a);
Â* Â* return 0;
}
struct test funTest()
{
Â* Â* Â* Â*struct test foo;
Â* Â* Â* Â*strcpy(foo.a, "Hello");
Â* Â* Â* Â*return foo;
}
In this I want to know how the following expression statement works:
printf("%s",fun Test().a);
funTest() is evaluated to yield an rvalue of type, "struct test" and
the expression "funTest(). a" yields an rvalue of type array of char,
which is converted to an rvalue equal to the pointer to the first
element of the char array and is passed to the printf() function.

Correct.
My doubt is, since "funTest(). a" yields an rvalue of type, array of
char, how can it be converted to pointer type when we can have pointer
only for Lvalues and not for Rvalues.

The pointer points to a temporary, and accessing that temporary after
the next sequence point, or modifying it, results in undefined
behaviour. (If you don't know what a sequence point is, please ask.)

char c = funTest().a[0]; /* valid, initialises c with 'H' */
char *p = funTest().a; /* valid, initialised p with a pointer value */
c = *p; /* invalid, accessing the function call's result after the
next sequence point */

funTest().a[0] = 'H'; /* invalid, modifying function call's result */
Forgot to ask you one more question.
The left operand of assignment operator should be an Lvalue, but in
this case it is an rvalue, but the compiler doesn't complain that
"Lvalue required". So can I conclude that a structure containing an
array type returned by a function is converted from Rvalue to Lvalue!
(Really funny!!)
Or is it Compiler dependent?
Does the standard say anything about the value returned by, functions
returning structure containing array type?
I hope my question is clear.

Thanks in advance for the reply.
>
char str[100];
strcpy(str, funTest().a); /* invalid, accessing the function call's
result after the next sequence point */- Hide quoted text -

- Show quoted text -

Mar 10 '07 #4
On Mar 10, 11:38 am, "SRR" <SRRajesh1...@g mail.comwrote:
On Mar 10, 2:51 pm, "Harald van Dijk" <true...@gmail. comwrote:SRRwro te:
Consider the following code:
#include <stdio.h>
#include <string.h>
struct test{
char a[100];
}
funTest( void );
int main( void )
{
printf("%s",fun Test().a);
return 0;
}
struct test funTest()
{
struct test foo;
strcpy(foo.a,"H ello");
return foo;
}
[...]
char c = funTest().a[0]; /* valid, initialises c with 'H' */
char *p = funTest().a; /* valid, initialised p with a pointer value */
c = *p; /* invalid, accessing the function call's result after the
next sequence point */
funTest().a[0] = 'H'; /* invalid, modifying function call's result */
char str[100];
strcpy(str, funTest().a); /* invalid, accessing the function call's
result after the next sequence point */

Let us extend the topic. Is this the only case, when an rvalue of type
array is converted to rvalue of type pointer to the first element of
the array using temporary storage?
A structure that is not a function call's result must be an lvalue, as
far as I know. So yes, I believe this is the only special case.

Mar 10 '07 #5
On Mar 10, 12:03 pm, "SRR" <SRRajesh1...@g mail.comwrote:
On Mar 10, 2:51 pm, "Harald van Dijk" <true...@gmail. comwrote:
funTest().a[0] = 'H'; /* invalid, modifying function call's result */

Forgot to ask you one more question.
The left operand of assignment operator should be an Lvalue, but in
this case it is an rvalue, but the compiler doesn't complain that
"Lvalue required". So can I conclude that a structure containing an
array type returned by a function is converted from Rvalue to Lvalue!
funTest().a[0] is short for *(funTest().a + 0).

funTest().a is an rvalue array, funTest().a + 0 is an rvalue pointer,
and *(funTest().a + 0) is a dereferenced pointer. Any dereferenced
pointer is an lvalue. There is no rvalue-to-lvalue conversion that
takes place.

The difference can matter:

struct S {
char m[1];
};
struct S s;
struct S f(void) {
return s;
}
int main(void) {
char *p;
p = s.m; /* valid */
p = (char *) &s.m; /* valid */
p = f().m; /* valid (but useless) */
p = (char *) &f().m; /* invalid */
}

The last statement is invalid because f().m is not an lvalue, so you
cannot apply to & operator to it. (The compiler I'm trying right now
disagrees with me; I might be wrong on this.)

Mar 10 '07 #6
[regarding a function, in this case named "funTest", that returns
a structure "struct test", containing an array, in this case "a"]
>SRR wrote:
>>In this I want to know how the following expression statement works:
printf("%s",fu nTest().a);

funTest() is evaluated to yield an rvalue of type, "struct test" and
the expression "funTest(). a" yields an rvalue of type array of char,
which is converted to an rvalue equal to the pointer to the first
element of the char array and is passed to the printf() function.
In article <11************ *********@8g200 0cwh.googlegrou ps.com>
Harald van Dijk <tr*****@gmail. comwrote:
>Correct.
[...]
>The pointer points to a temporary, and accessing that temporary after
the next sequence point, or modifying it, results in undefined
behaviour. (If you don't know what a sequence point is, please ask.)

char c = funTest().a[0]; /* valid, initialises c with 'H' */
It is worth adding that this is new in C99. C89 never really
quite said enough about these things: we can make guesses, but
there is no wording in that standard to pin down the behavior.
In C89, even something like:

char c = funTest().a[0];

might not be valid. (One might hope that it *is* valid, with the
semantics required by C99, but I think it is dangerous to assume
so.) Note that:

struct test val;

val = funTest();

is valid in both C89 and C99, and is "safe way" to handle
structure-valued functions.
--
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.
Mar 10 '07 #7
On Mar 10, 10:02Â*pm, "Harald van Dijk" <true...@gmail. comwrote:
On Mar 10, 12:03 pm, "SRR" <SRRajesh1...@g mail.comwrote:
On Mar 10, 2:51 pm, "Harald van Dijk" <true...@gmail. comwrote:
funTest().a[0] = 'H'; /* invalid, modifying function call's result */
Forgot to ask you one more question.
The left operand of assignment operator should be an Lvalue, but in
this case it is an rvalue, but the compiler doesn't complain that
"Lvalue required". So can I conclude that a structure containing an
array type returned by a function is converted from Rvalue to Lvalue!

funTest().a[0] is short for *(funTest().a + 0).

funTest().a is an rvalue array, funTest().a + 0 is an rvalue pointer,
and *(funTest().a + 0) is a dereferenced pointer. Any dereferenced
pointer is an lvalue. There is no rvalue-to-lvalue conversion that
takes place.

The difference can matter:

struct S {
Â* Â* char m[1];};

struct S s;
struct S f(void) {
Â* Â* return s;}

int main(void) {
Â* Â* char *p;
Â* Â* p = s.m; /* valid */
Â* Â* p = (char *) &s.m; /* valid */
Â* Â* p = f().m; /* valid (but useless) */
Â* Â* p = (char *) &f().m; /* invalid */

}

The last statement is invalid because f().m is not an lvalue, so you
cannot apply to & operator to it. (The compiler I'm trying right now
disagrees with me; I might be wrong on this.)
Thanks, You are right.
My compiler Dev-CPP, gives Lvalue required error for the statement:
p = (char *) &f().m; /* invalid */

And I think it is even more "intelligen t" enough to point out that the
statement:
p = f().m; /* valid (but useless) */
is useless and generates an error "invalid use of non-lvalue array"!

Now I modified the Code u gave:
#include <stdio.h>
struct S {
char m[1];
};
struct S s;
struct S f(void) {

return s;

}
int main(void) {
char *p;
printf("%s",(ch ar*)f().m);/*Note Explicit casting to (char*) */

}

I know that I'm invoking UB by the following statement, if executed,:

printf("%s",(ch ar*)f().m);/* Note Explicit casting to (char*) */

But the above statement is not compiling and gives an error:

"cannot convert to a pointer type"

But C standard guarantees that any pointer can be converted to (char*)
and back without causing any error or UB.
So I guess the assertion, "expression f().m is evaluated to yield an
rvalue pointer" is wrong and it remains as an rvalue array type only,
which is further clarified by the following code:
struct S {
char m[1];
};
struct S s;
struct S f(void) {

return s;

}
int main(void) {
char *p;
*(f().m+0) = 'a';/*Compiler complains*/

}

Compiler gives an error corresponding to the line:
*(f().m+0) = 'a';/*Compiler complains*/
The error is
"invalid operands to binary + "
which is possible only when f().m is an array type and not a pointer
type as we might think. So there is no conversion from array type to
pointer type here, *though C standard requires it*!

But, how the expression statement:
f().m[0] = 'a';
gets executed when f().m is not converted to pointer type?

Note that when we give statement like the following:

printf("%s",f() .m);/* I am invoking a UB, but leave it! */

The compiler compiles without any error because printf() is a variable
argument function and there is no way to check the type of each
argument, though there is no possibility of passing an array as such
in C!(except in this case, I guess!)

Do reply about my comments and correct me if I'm wrong.

Mar 11 '07 #8
On Mar 10, 10:02Â*pm, "Harald van Dijk" <true...@gmail. comwrote:
On Mar 10, 12:03 pm, "SRR" <SRRajesh1...@g mail.comwrote:
On Mar 10, 2:51 pm, "Harald van Dijk" <true...@gmail. comwrote:
funTest().a[0] = 'H'; /* invalid, modifying function call's result */
Forgot to ask you one more question.
The left operand of assignment operator should be an Lvalue, but in
this case it is an rvalue, but the compiler doesn't complain that
"Lvalue required". So can I conclude that a structure containing an
array type returned by a function is converted from Rvalue to Lvalue!

funTest().a[0] is short for *(funTest().a + 0).

funTest().a is an rvalue array, funTest().a + 0 is an rvalue pointer,
and *(funTest().a + 0) is a dereferenced pointer. Any dereferenced
pointer is an lvalue. There is no rvalue-to-lvalue conversion that
takes place.

The difference can matter:

struct S {
Â* Â* char m[1];};

struct S s;
struct S f(void) {
Â* Â* return s;}

int main(void) {
Â* Â* char *p;
Â* Â* p = s.m; /* valid */
Â* Â* p = (char *) &s.m; /* valid */
Â* Â* p = f().m; /* valid (but useless) */
Â* Â* p = (char *) &f().m; /* invalid */

}

The last statement is invalid because f().m is not an lvalue, so you
cannot apply to & operator to it. (The compiler I'm trying right now
disagrees with me; I might be wrong on this.)

Sorry, I forgot to mention an important thing.
I recently subscribed to this group and I gave my full name
Rajesh S R
for subscription, which is abbreviated as SRR in the above posts!
So dont get confused by the new name in the recent post!!

I know that, what I said just now might be irrelevant, but I dont want
to confuse people unnecessarily!!

Mar 11 '07 #9
Rajesh S R wrote:
On Mar 10, 10:02Â*pm, "Harald van Dijk" <true...@gmail. comwrote:
On Mar 10, 12:03 pm, "SRR" <SRRajesh1...@g mail.comwrote:
On Mar 10, 2:51 pm, "Harald van Dijk" <true...@gmail. comwrote:
funTest().a[0] = 'H'; /* invalid, modifying function call's result */
Forgot to ask you one more question.
The left operand of assignment operator should be an Lvalue, but in
this case it is an rvalue, but the compiler doesn't complain that
"Lvalue required". So can I conclude that a structure containing an
array type returned by a function is converted from Rvalue to Lvalue!
funTest().a[0] is short for *(funTest().a + 0).

funTest().a is an rvalue array, funTest().a + 0 is an rvalue pointer,
and *(funTest().a + 0) is a dereferenced pointer. Any dereferenced
pointer is an lvalue. There is no rvalue-to-lvalue conversion that
takes place.

The difference can matter:

struct S {
Â* Â* char m[1];};

struct S s;
struct S f(void) {
Â* Â* return s;}

int main(void) {
Â* Â* char *p;
Â* Â* p = s.m; /* valid */
Â* Â* p = (char *) &s.m; /* valid */
Â* Â* p = f().m; /* valid (but useless) */
Â* Â* p = (char *) &f().m; /* invalid */

}

The last statement is invalid because f().m is not an lvalue, so you
cannot apply to & operator to it. (The compiler I'm trying right now
disagrees with me; I might be wrong on this.)

Thanks, You are right.
My compiler Dev-CPP, gives Lvalue required error for the statement:
p = (char *) &f().m; /* invalid */

And I think it is even more "intelligen t" enough to point out that the
statement:
p = f().m; /* valid (but useless) */
is useless and generates an error "invalid use of non-lvalue array"!
Yes, I now see that too that I'm using GCC. It converts non-lvalue
arrays to pointers only in C99 mode (using the -std=c99 command-line
option). I missed that it's new in C99, but Chris Torek explained it
quite well. This also applies to the rest of your post.

Mar 11 '07 #10

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

Similar topics

11
2080
by: JKop | last post by:
The following compiles: // syrup.cpp struct DoubleInDisguise { double data; };
24
2969
by: Romeo Colacitti | last post by:
Hi, Does anyone here have a strong understanding for the meanings of the terms "lvalue" and "rvalue" as it pertains to C, objects, and different contexts? If so please share. I've been reading several old posts/threads on the subject, and they never end with a conclusion (people keep correcting each other and disagreeing).
1
2290
by: Hemant Mohan | last post by:
Consider the following program snipet: <snip> typedef struct { unsigned char a ; unsigned char b ; unsigned char c ;
0
1388
by: mseeger | last post by:
My concrete problem is this (it is a bit special, but there may be other instances of it): I'd like to create a class for vectors (say: Vector), exporting math. methods, say v.foo(...). I'd like to implement 'operator()' s.t. I can treat parts of a vector in the same way as a normal vector: if v.foo(...) works, so should v(rng).foo(...), where rng is a range object. This should work even if 'foo' is a non-const method. I do this by...
6
2913
by: Lighter | last post by:
How to read "The lvalue-to-rvalue, array-to-pointer, and function-to- pointer standard conversionsare not applied to the left expressions"? In 5.18 Comma operator of the C++ standard, there is a rule: "The lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard conversionsare not applied to the left expressions" I could not understand what the rule means. I also searched the web and the groups and got nothing.
1
1727
by: Chris Fairles | last post by:
Take the following snip (pretend A its a std::pair if you wish ;) ) template <class T1,class T2> struct A { A(A const&){cout<<"A(const&) ";} A(A&&){cout<<"A(A&&) ";} A(T1 const&, T2 const&){cout<<"A(T1,T2) ";} template<class U1, class U2> A(A<U1,U2&&) {cout<<"A(A<U1,U2>&&) ";}
1
1347
by: George2 | last post by:
Hello everyone, I do not know how in the following code, rvalue -- return of X(), could result in a lvalue finally and binded to a non-const reference input parameter of function f. Any ideas?
0
1345
by: Frank Bergemann | last post by:
Using gcc-4.3.0 it silenty(!) invokes the Test::operator=(Test const& t) for Test a; Test b = std::move(a); Test c = std::moved(T()); - if i disable the Test::operator=(Test&& t) in source file. (But uses Test::operator=(Test&& t) if it is availabled.)
2
1770
by: Chad | last post by:
The following question actually stems from an old Chris Torek post. And I quote from the following old CLC url http://groups.google.com/group/comp.lang.c/browse_thread/thread/ce93f8bf3e61aede/cfeed3fda1d0ee46?hl=en&lnk=gst&q=convert+lvalue+to+rvalue#cfeed3fda1d0ee46 "Mathematically speaking, unary `&' and `*' are inverse functions. Unary `&' takes an lvalue of type `T' and produces an rvalue of type `pointer to T'; unary `*' takes an...
0
10569
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10325
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10315
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10075
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7615
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 presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6847
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
1
4295
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3815
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2990
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.