views:

307

answers:

5

I have a pointer of a structure type that I made. On program start it begins as NULL and I then malloc/realloc as I need to add/remove these structures and I was just gonna use my pointer to point at the first structure and move through it like an array.

When I malloc/realloc I always make the size of the "array"/area in memory one larger than it needs to be. I do this so I can set the "last index"/area in memory to NULL so I can say something like while (pointer != NULL).

I get the error: invalid lvalue in assignment when I try to assign NULL to the last position in the array/area of memory with the lines:

  // Realloc remotelist by adding one to connrhosts
  connrhosts++;
  remotelist = realloc(remotelist, sizeof(rhost)*(connrhosts + 1));
  (remotelist + connrhosts) = NULL;

What I think I am saying is:

  • Its time to add a new structure to my array so I will increase connrhosts by one.
  • Realloc the memory that is pointed at remotelist to a new area of memory that is the size of connrhosts (how many structures I will use) as well as one additional space so I can make it NULL
  • Point remotelist to the new area of memory
  • Use my pointer remotelist and add the offset connrhosts which will now point to the last index of the area of memory and make that pointer NULL.

As far as I can tell (or feel) I did everything correctly, but I have been working on this project for sometime now and am under the impression I have tunnel vision. I would love to have a fresh set of eyes take a look at my logic/code and let me know what they think and what I did wrong. Thanks again. :D

Edit - Part of my problem is I think I have a misunderstanding of what I can do with pointers.

Here is my structure:

typedef struct {
  char address[128]; // Buffer that holds our address of the remote host
  int port; // Port of the remote host
  int conn; // FD to the connection of our remote host
  int ofiles; // Open files associated with the remote host
} rhost;

What I was hoping I could do was loop through my array/area of memory and say if its not NULL then do something with it. So my original loop statement is while (NULL != remotelist). Now I believe are reading responses and comments that this logic is wrong because I am checking if a pointer is null? I ought to be checking if the area of memory/structure that the pointer is pointing is null? If this is the case it ought to be something like while (NULL != *(remotelist + someoffset))?

I am doing it this way as my teacher suggested it/talked about it in class.

My initial declaration/initialization of remotelist was: rhost *remotelist = NULL;

+4  A: 

Edit - not happy with how I first explained it.

Errornous lvalue assignments occur when the LHS is an evaluated expression that does not become a variable that can be assigned. What you're doing looks like an operation (pointer arithmetic) which should be on the RHS.

What you can do is:

remotelist[connrhosts] = NULL;  // array notation asuming 
                                // remotelist is an array of pointers

assuming connrhosts is a int or size_t or you could do:

remotelist += connrhost; // pointer arithmetic
*remotelist = NULL; // assuming remotelist is an array of pointers.
Ninefingers
Won't remotelist += connrhost; // pointer arithmetic*remotelist = NULL;actually change the address of where my pointer is pointing at? If so that would be a problem for me. I was adding the offset or connrhosts so I could say "This many spots away from the beginning make NULL". I also provided more documentation on my structure and what I thought I was doing.
Chris
Yes, it does, it increments the pointer by connrhost blocks of the type of remotelist. You'd have to move it back again afterwards. I included both options for completeness. I gave +1 to the answer below that suggested the [] notation was cleaner - it is.
Ninefingers
I went ahead and tried using the [] notation but then I got a incompatible types in assignment error. So I must be doing something wrong earlier or I just really have no idea what I am doing?
Chris
It sounds like you've got the types messed up somewhere, but have a look at Steve Jessop's comment on your question. It sounds like you're trying to emulate strings, which are terminated with the `\0` character. That's actually equal to 0, so the last int is a 0 if that makes sense, which is different to NULL, which is a void * to nothing.
Ninefingers
+2  A: 

You need to derereference the pointer with * to access what is stored at the memory addressed by the pointer.

*(remotelist + connrhosts) = NULL;
binarycoder
+2  A: 

You also need to dereference your pointer.

*(remotelist + connrhosts) = NULL;

Although I think

 remotelist[connrhosts] = NULL; 

is clearer.

John Knoeller
A: 

The expression pointer != NULL refers to the pointer itself, not the memory that the pointer references. Even if you could assign NULL to it, that won't solve the problem.

After incrementing the pointer, it isn't NULL, it has an address in it, the address of your last, extra, struct slot.

You could, I suppose, set this area to 0's with:

memset(remotelist + connrhosts, 0, sizeof(rhost));

Then you could do something like p->field == 0 if this field is never 0 on a real struct...

Personally, I would handle this issue, if I understand it correctly, by either allocating a second array of pointers to the structures, or by just keeping track of how many I have, or, most likely, by using a collection such as a linked list or tree, that is, something with more graceful expansion operations than realloc().

DigitalRoss
A: 

"Area of memory/structure" cannot be assigned NULL and cannot be compared to NULL. NULL is only used with pointers.

If you want to set all fields of a [newly allocated] structure to zeros, in C89/90 the common idiom is to do it with the help of = { 0 } initializer:

const rhost ZERO_HOST = { 0 };
...
connrhosts++; 
remotelist = realloc(remotelist, connrhosts * sizeof *remotelist); 
remotelist[connrhosts] = ZERO_HOST; 

Or you can simply use memset (which is a hack).

As for checking whether the entry in your array is all-zeroes... There's no built-in operation for that, although memcmp function can help

if (memcmp(&remotelist[i], &ZERO_HOST, sizeof ZERO_HOST) == 0)
  /* All zeroes */;

(this is also a bit of a hack, albeit less "hackish" that the memset one).

but it is not normally done that way. And there's really no point in doing it that way. Normally, you should simply select just one field in your structure (a "primary" one) that can tell you whether the structure is "used: or not and compare just that single field to 0

if (remotelist[i].address[0] == '\0')
  /* Entry is not used */;
AndreyT