Different behaviour in different struct declaration types

P

__PaTeR

These days i'm writing so much , now i was learning something about
lists... In my code i have a while loop that ends up only when the
NEXT member of the struct is equal to NULL; ( i'm just surfing in the
list )

Finding some good resource about structures has been really hard, for
example, i found out by myself the difference between the 2 operators -
and . ... or at least i think i found it out.

As i've seen through gdb and experiments, is that: when you declare a
struct this way:
struct lista a;

To access the members u have to use the dot, and "a" doesn't contain
the pointer to the memory, but the memory itself, just like an
integer.

Besides, if u declare it this way:
struct lista *q; /* = malloc... etc */

q is just a pointer to a memory region, just like a char definition
( char *a ). To access members you have to use the arrow -> .... don't
you?

SO: why this

struct lista *q = malloc(sizeof(struct lista));
q->num=n;
q->next = NULL;

works really good, but this one:

struct lista a;
a.num = n;
a.next = NULL;

does not?? This last code let my while ends never! And i ould the
reason, look at this gdb output:

-----------------------
(gdb) print a.next
$2 = (struct lista *) 0x0
(gdb) print a
$3 = {num = 1, next = 0x0}
(gdb) print &a
$4 = (struct lista *) 0xbfb4000c
(gdb) x $4
0xbfb4000c: 0x00000001
(gdb) x $4+4
0xbfb4002c: 0x08048b28
(gdb) print $4+4
$5 = (struct lista *) 0xbfb4002c <---- 1
(gdb) x $5
0xbfb4002c: 0x08048b28 <------ 2
(gdb) print $5
$6 = (struct lista *) 0xbfb4002c <----- 1
(gdb) x $6
0xbfb4002c: 0x08048b28 <------- 2
(gdb) quit
 
K

Keith Thompson

__PaTeR said:
These days i'm writing so much , now i was learning something about
lists... In my code i have a while loop that ends up only when the
NEXT member of the struct is equal to NULL; ( i'm just surfing in the
list )

Finding some good resource about structures has been really hard,
for example, i found out by myself the difference between the 2
operators -> and . ... or at least i think i found it out.

It shouldn't be that hard; any decent C textbook should explain this.
K&R2 (Kernighan & Ritchie, "The C Programming Language", 2nd Edition)
is widely considered to be an excellent book. See also question 18.10
in the comp.lang.c FAQ said:
As i've seen through gdb and experiments, is that: when you declare a
struct this way:
struct lista a;

To access the members u have to use the dot, and "a" doesn't contain
the pointer to the memory, but the memory itself, just like an
integer.

Besides, if u declare it this way:
struct lista *q; /* = malloc... etc */

q is just a pointer to a memory region, just like a char definition
( char *a ). To access members you have to use the arrow -> .... don't
you?

Correct. "x->y" is an abbreviation for "(*x).y". But I'm at a loss
to understand why you needed "gdb and experiments" to learn this.
SO: why this

struct lista *q = malloc(sizeof(struct lista));
q->num=n;
q->next = NULL;

works really good, but this one:

struct lista a;
a.num = n;
a.next = NULL;

does not?? This last code let my while ends never! And i ould the
reason, look at this gdb output: [snip]
As you can see, the last 4 outputs show the reason of the infinite
loop.... But i ask.... why?

You've shown us the code that initializes the struct object, but you
haven't shown us either the declaration of the struct type itself or
the code that traverses the list. Without seeing the code, we can't
possibly guess what might be causing the problem. Well, maybe we
could; if I spent enough time studying your description and your gdb
output, I might be able to reconstruct what's going on. But I'm not
going to expend the effort.

Post a complete program (compilable and executable) that illustrates
your problem. Tell us what you expected it to do, what it actually
did, and how those differ. Try to keep your program fairly small.

(And it's spelled "you", not "u". This is a newsgroup, not a chat
room.)
 
P

__PaTeR

sorry for the 'u', writing fast i often forget the 'yo' :\

And also sorry for the rest of the code: here it's the compilable:

I first tried to apply the structs in an already-functional program,
but when i figured out thing were getting dirty, i wrote a test
program to expecially study lists:

#include <stdio.h>
#include <stdlib.h>

struct lista {
int num;
struct lista *next;
};

void stampa(struct lista *list) {
struct lista *i;
for(i = list; i != NULL; i=i->next )
printf("%d\n", i->num);
}

void inserisci(struct lista *p, int n)
{
struct lista *q = malloc(sizeof(struct lista));
q->num=n;
q->next = NULL;
p->next = &a;
}


void appendi(int num, struct lista *q) {
while ( q->next != NULL && q->next->num < num) {
q = q->next;
}
inserisci(q, num);
}

int main() {
struct lista *a = malloc(sizeof(struct lista));
a->next = NULL;
appendi(1, a);
appendi(5, a);
appendi(9, a);
stampa(a);

return 0;
}

Function and structs names are in italian... but i think code is
obviously readable to everyone.
 
K

Keith Thompson

__PaTeR said:
sorry for the 'u', writing fast i often forget the 'yo' :\

And also sorry for the rest of the code: here it's the compilable:

No, it isn't.

[...]
void inserisci(struct lista *p, int n)
{
struct lista *q = malloc(sizeof(struct lista));
q->num=n;
q->next = NULL;
p->next = &a;
}
[...]

"a" is undeclared. Always copy-and-paste your code, making sure it's
*exactly* the same code that you fed to the compiler. If you re-type
it, you'll almost inevitably introduce errors, making it impossible
for us to tell which problems actually occur in your original code.

When I change "p->next = &a;" to "p->next = &q;", I get

warning: assignment from incompatible pointer type

When I change it to "p->next = q;", it compiles no diagnostics, and
produces the following run-time output:

0
1
5
9

Since you didn't, as I requested, tell us either what output you got
or what output you expected, it's difficult to tell whether that's
correct or not.

A couple of notes on your code:

You don't check whether malloc() succeeded. That's probably ok in a
tiny demo like this, but you should at least add a comment saying that
you've dropped any error checking.

It appears that each time you append a new item to your linked list,
you traverse from the head to the tail before appending it. This can
be grossly inefficient for long lists. Either insert at the head, or
keep track of the tail.

The commonly recommended idiom for malloc is:

ptr = malloc(sizeof *ptr);

In your case:

struct lista *q = malloc(sizeof *q);

There will probably be some vocal disagreement on this point, but it
has the advantage that you don't have to repeat the type, so there's
no risk of getting it wrong.
 
K

Keith Thompson

pete said:
Keith said:
__PaTeR said:
sorry for the 'u', writing fast i often forget the 'yo' :\

And also sorry for the rest of the code: here it's the compilable:
No, it isn't.
[...]
void inserisci(struct lista *p, int n)
{
struct lista *q = malloc(sizeof(struct lista));
q->num=n;
q->next = NULL;
p->next = &a;
}
[...]
"a" is undeclared. Always copy-and-paste your code, making sure it's
*exactly* the same code that you fed to the compiler. If you re-type
it, you'll almost inevitably introduce errors, making it impossible
for us to tell which problems actually occur in your original code.
When I change "p->next = &a;" to "p->next = &q;", I get
warning: assignment from incompatible pointer type
When I change it to "p->next = q;", it compiles no diagnostics, and
produces the following run-time output:
0
1
5
9

When *I* change it to "p->next = q;", it compiles no diagnostics, and
produces the following run-time output:

-842150451
1
5
9

The first node in the list, allocated in main(), never has its "n"
member initialized.

It would be simpler to set up an initially empty list, and call
appendi() for each node to be appended.
 
G

Guest

These days i'm writing so much , now i was learning something about
lists... In my code i have a while loop that ends up only when the
NEXT member of the struct is equal to NULL; ( i'm just surfing in the
list )

Finding some good resource about structures has been really hard, for
example, i found out by myself the difference between the 2 operators
[->] and . ... or at least i think i found it out.

get a good text book. Eg. K&R
As i've seen through gdb and experiments, is that: when you declare a
struct this way:
struct lista a;

To access the members u have to use the dot, and "a" doesn't contain
the pointer to the memory, but the memory itself, just like an
integer.

Besides, if u declare it this way:
struct lista *q; /* = malloc... etc */

q is just a pointer to a memory region, just like a char definition
( char *a ). To access members you have to use the arrow -> .... don't
you?

SO: why this

struct lista *q = malloc(sizeof(struct lista));
q->num=n;
q->next = NULL;

works really good, but this one:

struct lista a;
a.num = n;
a.next = NULL;

does not??

there's no reason why the above "shouldn't work" (whatever /that/
means).
Post your code.
This last code let my while ends never! And i ould the
reason, look at this gdb output:

<snip>

I'd rather see your code
 
B

Barry Schwarz

snip
/* BEGIN listi.c */

#include <stdio.h>
#include <stdlib.h>

struct listi {
struct listi *next;
int num;
};

void stampi(struct listi *i)
{
while (i != NULL) {
printf("%d\n", i -> num);
i = i -> next;
}
}

struct listi *appendi(struct listi **head, struct listi *tail, int data)
{
struct listi *node;

node = malloc(sizeof *node);
if (node != NULL) {
node -> next = NULL;
node -> num = data;
if (*head != NULL) {

On the first call (data == 1), *head is NULL.

On the second call (data == 5), * head points to N1 but tail is still
NULL.
tail -> next = node;

On the second call, this dereferences a NULL tail and invokes
undefined behavior.
} else {
*head = node;

On the first call, *head is set to point to the first node (call it
N1)
}
}
return node;
}

void freei(struct listi *q)
{
struct listi *next_node;

while (q != NULL) {
next_node = q -> next;
free(q);
q = next_node;
}
}

int main(void)
{
struct listi *a = NULL;
struct listi *b = NULL;

At no point is b ever changed.
 
B

Barry Schwarz

(b) is assigned the return value from malloc,
which tends to be a different value each time that appendi is called.

You're right and I have no idea why I missed it. Sorry for wasting
your time.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top