473,385 Members | 1,912 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,385 software developers and data experts.

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(writev, cfg->fd, iov, iovcnt)) <= 0);

-OR-

if (transmit_iov(writev, 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=release --with-system-zlib --enable-__cxa_atexit
--disable-libunwind-exceptions --enable-libgcj-multifile
--enable-languages=c,c++,objc,obj-c++,java,fortran,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_DEBUG -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(ssize_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 7791


On Oct 6, 10:29 pm, "A. Farber" <Alexander.Far...@gmail.comwrote:
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(writev, cfg->fd, iov, iovcnt)) <= 0);

-OR-

if (transmit_iov(writev, 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=release --with-system-zlib --enable-__cxa_atexit
--disable-libunwind-exceptions --enable-libgcj-multifile
--enable-languages=c,c++,objc,obj-c++,java,fortran,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_DEBUG -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(ssize_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.programmer A. Farber <Al**************@gmail.comwrote:
It has always worked until I switched to FC5 Linux which uses:
$ gcc -Wall -I common -ggdb -O0 -DQUEUE_MACRO_DEBUG -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
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...
9
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...
14
by: Michael Ovetsky | last post by:
Consider: int g(){int b=1; return b;} int main() { int d=2; g()=d; }
9
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...
1
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
by: Paul Edwards | last post by:
The following code: int main(void) { char *x; (void **)x += 1; return (0); }
6
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
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
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,...
10
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...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
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: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
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
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
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,...
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...

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.