473,714 Members | 2,681 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Invalid lvalue in assignment when trying to advance a void-pointer (struct iovec)

Hello,

I call readv() and writev() in several spots of a program which I run
under Linux, OpenBSD and Cygwin. Since it always the same way
(check the return value; then check errno and retry if EAGAIN/EINTR),
I've written a wrapper function (full source code on the bottom)
to call those functions and just pass the function pointer to it:

do {
...
} while ((n = transmit_iov(wr itev, cfg->fd, iov, iovcnt)) <= 0);

-OR-

if (transmit_iov(w ritev, pkid->fd, iov, 2) <= 0) {
...
}

It has always worked until I switched to FC5 Linux which uses:

$ gcc -v
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info --enable-shared --enable-threads=posix
--enable-checking=releas e --with-system-zlib --enable-__cxa_atexit
--disable-libunwind-exceptions --enable-libgcj-multifile
--enable-languages=c,c++ ,objc,obj-c++,java,fortra n,ada
--enable-java-awt=gtk --disable-dssi
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre
--with-cpu=generic --host=i386-redhat-linux
Thread model: posix
gcc version 4.1.1 20060525 (Red Hat 4.1.1-1)

Now my compilation fails with:

$ gcc -Wall -I common -ggdb -O0 -DQUEUE_MACRO_DE BUG -D_GNU_SOURCE
-I openbsd-compat -I /usr/include -c common/common.c -o build/common.o
common/common.c: In function 'transmit_iov':
common/common.c:58: error: invalid lvalue in assignment

My problem is that I have an array struct iovec iov[], which is:

struct iovec {
void *iov_base; /* Starting address */
size_t iov_len; /* Number of bytes */
};

In my code I'm trying to advance the iov_base by the number of
bytes I have successfully transmitted in the previous readv/writev
call:

/* only part of iov[i].iov_base transmitted */
if (n < iov[i].iov_len) {
/* the troublesome line 58 */
(char *)iov[i].iov_base += n;
iov[i].iov_len -= n;
break;
}

And that's where gcc 4.x (or my code) is failing.

Does anybody please have a hint or solution for this probably
frequent problem: How to advance a void-pointer by few bytes?

Thank you
Alex

PS: and here is my wraper function for readv/writev():
/* The fp is either readv or writev; the iov array is not const */
int
transmit_iov(ss ize_t (*fp)(int, const struct iovec*, int),
int fd, struct iovec iov[], int iovcnt)
{
int n;
unsigned i = 0;

while (i < iovcnt) {
/* skip eventual elements with iov_len=0
at the end of iov */
if (0 == iov[i].iov_len) {
i++;
continue;
}
/* keep retrying if interrupted by a signal
or would block */
do
n = (*fp)(fd, &iov[i], iovcnt - i);
while (-1 == n && (EINTR == errno || EAGAIN == errno));
/* give up on real failure or terminated connection */
if (n <= 0)
return n;
/* n bytes successfully transmitted, adjust iov[] */
while (n 0) {
/* only part of iov[i].iov_base transmitted */
if (n < iov[i].iov_len) {
(char *)iov[i].iov_base += n; /* line 58 */
iov[i].iov_len -= n;
break;
/* one array element transmitted completely */
} else {
n -= iov[i].iov_len;
i++;
}
}
}
return i;
}
--
http://preferans.de

Oct 6 '06 #1
5 7814


On Oct 6, 10:29 pm, "A. Farber" <Alexander.Far. ..@gmail.comwro te:
Hello,

I call readv() and writev() in several spots of a program which I run
under Linux, OpenBSD and Cygwin. Since it always the same way
(check the return value; then check errno and retry if EAGAIN/EINTR),
I've written a wrapper function (full source code on the bottom)
to call those functions and just pass the function pointer to it:

do {
...
} while ((n = transmit_iov(wr itev, cfg->fd, iov, iovcnt)) <= 0);

-OR-

if (transmit_iov(w ritev, pkid->fd, iov, 2) <= 0) {
...
}

It has always worked until I switched to FC5 Linux which uses:

$ gcc -v
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info --enable-shared --enable-threads=posix
--enable-checking=releas e --with-system-zlib --enable-__cxa_atexit
--disable-libunwind-exceptions --enable-libgcj-multifile
--enable-languages=c,c++ ,objc,obj-c++,java,fortra n,ada
--enable-java-awt=gtk --disable-dssi
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre
--with-cpu=generic --host=i386-redhat-linux
Thread model: posix
gcc version 4.1.1 20060525 (Red Hat 4.1.1-1)

Now my compilation fails with:

$ gcc -Wall -I common -ggdb -O0 -DQUEUE_MACRO_DE BUG -D_GNU_SOURCE
-I openbsd-compat -I /usr/include -c common/common.c -o build/common.o
common/common.c: In function 'transmit_iov':
common/common.c:58: error: invalid lvalue in assignment

My problem is that I have an array struct iovec iov[], which is:

struct iovec {
void *iov_base; /* Starting address */
size_t iov_len; /* Number of bytes */
};

In my code I'm trying to advance the iov_base by the number of
bytes I have successfully transmitted in the previous readv/writev
call:

/* only part of iov[i].iov_base transmitted */
if (n < iov[i].iov_len) {
/* the troublesome line 58 */
(char *)iov[i].iov_base += n;
iov[i].iov_len -= n;
break;
}

And that's where gcc 4.x (or my code) is failing.

Does anybody please have a hint or solution for this probably
frequent problem: How to advance a void-pointer by few bytes?

Thank you
Alex

PS: and here is my wraper function for readv/writev():

/* The fp is either readv or writev; the iov array is not const */
int
transmit_iov(ss ize_t (*fp)(int, const struct iovec*, int),
int fd, struct iovec iov[], int iovcnt)
{
int n;
unsigned i = 0;

while (i < iovcnt) {
/* skip eventual elements with iov_len=0
at the end of iov */
if (0 == iov[i].iov_len) {
i++;
continue;
}
/* keep retrying if interrupted by a signal
or would block */
do
n = (*fp)(fd, &iov[i], iovcnt - i);
while (-1 == n && (EINTR == errno || EAGAIN == errno));
/* give up on real failure or terminated connection */
if (n <= 0)
return n;
/* n bytes successfully transmitted, adjust iov[] */
while (n 0) {
/* only part of iov[i].iov_base transmitted */
if (n < iov[i].iov_len) {
(char *)iov[i].iov_base += n; /* line 58 */
iov[i].iov_len -= n;
break;
/* one array element transmitted completely */
} else {
n -= iov[i].iov_len;
i++;
}
}
}
return i;

}--http://preferans.de
iov[i].iov_base = (char *)iov[i].iov_base + n; /* line 58 */

Oct 6 '06 #2
In comp.unix.progr ammer A. Farber <Al************ **@gmail.comwro te:
It has always worked until I switched to FC5 Linux which uses:
$ gcc -Wall -I common -ggdb -O0 -DQUEUE_MACRO_DE BUG -D_GNU_SOURCE
-I openbsd-compat -I /usr/include -c common/common.c -o build/common.o
common/common.c: In function 'transmit_iov':
common/common.c:58: error: invalid lvalue in assignment
/* the troublesome line 58 */
(char *)iov[i].iov_base += n;
And that can't really work. By using the cast you calculate a new
value. But a value is not a variable, so you can't assign another
value to it (that would require a so-called "lvalue"), you just
can use it in further calculations but not on the left hand side
of an assignment. The simple fix is, obviously, to use

iov[i].iov_base = (char *) iov[i].iov_base + n;

instead (conversion of the result to void * is done automatically
by the compiler, so no further cast is required). That it seemed
to work with other compilers doesn't mean that it's correct, just
that the GCC writers got further in writing a more standard com-
pliant C compiler;-)
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\______________ ____________ http://toerring.de
Oct 6 '06 #3

On Fri, 06 Oct 2006 07:29:02 -0700, A. Farber wrote:

[much detail, relevant to the question but not relevant to the answer]
common/common.c: In function 'transmit_iov':
common/common.c:58: error: invalid lvalue in assignment
My problem is that I have an array struct iovec iov[], which is:

struct iovec {
void *iov_base; /* Starting address */
size_t iov_len; /* Number of bytes */
};

In my code I'm trying to advance the iov_base by the number of
bytes I have successfully transmitted in the previous readv/writev
call:
/* the troublesome line 58 */
(char *)iov[i].iov_base += n;
Does anybody please have a hint or solution for this probably
frequent problem: How to advance a void-pointer by few bytes?
Ugly option (though casting the address of a variable to a pointer
of a different type is, WHEN CLEARLY UNDERSTOOD, a useful idiom):
*(char **)&(iov[i].iov_base) += n;

Not so ugly option, almost certainly equivalent in every way:
iov[i].iov_base = (char *)iov[i].iov_base + n;
Code:

#include <stdio.h>

struct iovec {
void *iov_base; /* Starting address */
size_t iov_len; /* Number of bytes */
};

int
main(int argc, char *argv[])
{
struct iovec iov[2] = {{0}};
int i = 1, n = 2;

printf("%p\n", iov[i].iov_base);

(char *)iov[i].iov_base += n; /* OP's error, my warning */
printf("%p\n", iov[i].iov_base);

*(char **)&(iov[i].iov_base) += n;
printf("%p\n", iov[i].iov_base);

iov[i].iov_base = (char *)iov[i].iov_base + n;
printf("%p\n", iov[i].iov_base);

return 0;
}
cc xmpl.c -o xmpl
xmpl.c: In function `main':
xmpl.c:16: warning: use of cast expressions as lvalues is deprecated

./xmpl
(nil)
0x2
0x4
0x6
Martin
--
Martin Golding DoD #0236 | fo*****@comcast .net
Always code as if the person who ends up maintaining your code will be a
violent psychopath who knows where you live.

Oct 6 '06 #4
Martin Golding wrote:
On Fri, 06 Oct 2006 07:29:02 -0700, A. Farber wrote:

[much detail, relevant to the question but not relevant to the answer]
common/common.c: In function 'transmit_iov':
common/common.c:58: error: invalid lvalue in assignment
My problem is that I have an array struct iovec iov[], which is:

struct iovec {
void *iov_base; /* Starting address */
size_t iov_len; /* Number of bytes */
};

In my code I'm trying to advance the iov_base by the number of
bytes I have successfully transmitted in the previous readv/writev
call:
/* the troublesome line 58 */
(char *)iov[i].iov_base += n;
Does anybody please have a hint or solution for this probably
frequent problem: How to advance a void-pointer by few bytes?

Ugly option (though casting the address of a variable to a pointer
of a different type is, WHEN CLEARLY UNDERSTOOD, a useful idiom):
*(char **)&(iov[i].iov_base) += n;
This isn't allowed in standard C, and GCC (which the OP was using) will
not make this code do what you expect it to, if certain optimisations
are enabled.

$ cat >test.c
#include <stdio.h>
int main(void) {
char a[] = { 1, 2, 3 };
void *p = a;
*(char **) &p += 2;
printf("%d\n", *(char *) p);
}
$ gcc -std=c99 -pedantic -Wall test.c -o test && ./test
3
$ gcc -std=c99 -pedantic -Wall test.c -o test -O2 && ./test
test.c: In function ‘main’:
test.c:5: warning: dereferencing type-punned pointer will break
strict-aliasing rules
1

Oct 6 '06 #5
Thank you all

Oct 6 '06 #6

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

Similar topics

19
36648
by: Hongzheng Wang | last post by:
In K&R, they said: An object is a named region of storage; an lvalue is an expression refer to an object. How about these concept in C++? `The C++ Programming Language' has a similar explanation, however, it may be too brief. Can anyone give me a more detailed explanation? Or give some referrences
9
3547
by: Steven T. Hatton | last post by:
This is from the draft of the previous version of the Standard: http://www.kuzbass.ru:8086/docs/isocpp/expr.html 2- A literal is a primary expression. Its type depends on its form (lex.literal). A string literal is an *lvalue*; all other literals are *rvalues*. -4- The operator :: followed by an identifier, a qualified-id, or an operator-function-id is a primary-expression. Its type is specified by the
14
2997
by: Michael Ovetsky | last post by:
Consider: int g(){int b=1; return b;} int main() { int d=2; g()=d; }
9
13740
by: junky_fellow | last post by:
Consider the following piece of code: (char *)0x100; /* I know that converting an integer to pointer type is implementation defined. But forget this for a moment */ My question is, Why the above expression is not an lvalue ? It both specifies the the storage location as well as the type of object ? When I try to increment it
1
3392
by: Tapeesh | last post by:
In C++, why does assignment operator always return a lvalue. Even in cases of assignment of basic datatypes like int ? For eg. int main() { int a, b, c; a = b + c; return 0;
6
4126
by: Paul Edwards | last post by:
The following code: int main(void) { char *x; (void **)x += 1; return (0); }
6
3023
by: Yarco | last post by:
I've alway thought lvalue means Left Value and rvalue means Right Value before i've read someone's article. It is said "lvalue = location value" and "rvalue = read value". Which one is right, then?
4
9062
by: mdh | last post by:
May I ask why this works: given: char s; char *posbfr = s; char *endbfr = s + MAXOP; void(...){ if (posbfr >= endbfr) printf("......");
1
2540
by: subramanian100in | last post by:
Consider the following: int x; int y; int z; (x+y) = z; For this statement, I get the following error with g++ compiler: error: non-lvalue in assignment Suppose I have a class Test and x, y, z are objects of type Test.
10
10494
by: muby | last post by:
Hi Everybody the compiler throws an error when it runs this function in my code, I couldn't figure out what is wrong with my code, please assist me, thanks :). void SMAC::IncreaseCW() { init rI=2; DATA_CW=DATA_CW*rI; double cw = (Random::random() % DATA_CW) * slotTime_sec_; mhCS_.sched(CLKTICK2SEC(difs_) + cw);
0
8797
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, well explore What is ONU, What Is Router, ONU & Routers main usage, and What is the difference between ONU and Router. Lets take a closer look ! Part I. Meaning of...
0
8704
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9010
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...
0
7946
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 projectplanning, coding, testing, and deploymentwithout human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6629
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
5945
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();...
0
4462
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3156
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
2514
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.