בעיה מוזרה - C

pitbol3

New member
בעיה מוזרה - C

אהלן חברים,

אני מנסה להריץ את הקוד הפשוט הזה שכל מטרתו הוא להקים רשימה מקושרת בת 3 איברים(וישנה עוד פונקציה שהוגדרה אך עדיין לא כתבתי אותה ולכן נעזוב אותה בצד).

כשאני מנסה להריץ את זה ב visual studio 2008, הוא מראה לי המון שגיאות ונראה שהוא בכלל לא הבין את ההגדרה של המבנה שביצעתי עם typedef.


אשמח לעזרה כאן כי נראה לי שפספסתי משהו...

תודה רבה !
 

pitbol3

New member
אממ

1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(6) : error C2061: syntax error : identifier 'item_'
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(6) : error C2059: syntax error : ';'
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(6) : error C2449: found '{' at file scope (missing function header?)
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(9) : error C2059: syntax error : '}'
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(11) : error C2143: syntax error : missing '{' before '*'
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(12) : error C2143: syntax error : missing '{' before '*'
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(12) : error C2143: syntax error : missing ')' before '*'
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(12) : error C2143: syntax error : missing '{' before '*'
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(12) : error C2059: syntax error : ')'
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(15) : error C2065: 'item' : undeclared identifier
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(15) : error C2297: '*' : illegal, right operand has type 'int *'
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(18) : error C2143: syntax error : missing '{' before '*'
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(19) : error C2065: 'item' : undeclared identifier
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(19) : error C2297: '*' : illegal, right operand has type 'int *'
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(19) : error C2065: 'temp' : undeclared identifier
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(19) : error C2109: subscript requires array or pointer type
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(20) : error C2143: syntax error : missing ';' before 'type'
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(21) : error C2065: 'i' : undeclared identifier
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(21) : error C2065: 'i' : undeclared identifier
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(21) : error C2065: 'i' : undeclared identifier
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(22) : error C2065: 'i' : undeclared identifier
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(23) : error C2065: 'item' : undeclared identifier
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(23) : error C2059: syntax error : ')'
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(24) : error C2223: left of '->data' must point to struct/union
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(27) : error C2065: 'temp' : undeclared identifier
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(27) : error C2065: 'i' : undeclared identifier
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(27) : error C2109: subscript requires array or pointer type
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(27) : error C2065: 'item' : undeclared identifier
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(27) : error C2059: syntax error : ')'
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(28) : error C2065: 'temp' : undeclared identifier
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(28) : error C2223: left of '->data' must point to struct/union
1>c:\users\חן\documents\visual studio 2008\projects\sdsadsa\sdsadsa\adsdsa.c(28) : error C2065: 'i' : undeclared identifier


גם ההערה שהבחור למטה אמר לא ממש עזרה...
 

nahsh

New member
לא כך מגדירים בC

להבדיל מ++C לדוגמא.

typedef sturct{
int data;
struct item *next;
}item;


אתה משתמש בitem לפני שהגדרת אותו. יש צורך בשם זמני כדי להשתמש בו בתוך הstruct, כי שם הטיפוס מוגדר רק אח"כ.

אם אני זוכר נכון, זה צריך להיות משהו כזה:
typedef sturct item_ {
int data;
struct item_ *next;
}item;


כלומר - _item הוא מעין שם זמני שמשמש אותנו בתוך ההגדרה בלבד. אח"כ משתמשים בitem. למה? מגבלות השפה והסינטקסט שלה.
 

nocgod

New member
אז זה לא נכון

אחרי תיקון שגיאות הכתיב (2 במספר) הקוד מתקמפל בvs ללא הערות ובgcc עם הערה שהmain חייב להחזיר int...
זה גם bad practice לתת שמות לדברים שלא צריכים שמות כי זה מזהם את מרחב השמות...למרות שיש אנשים יצירתיים וממציאים שמות בסגנון ___item___
זה עדיין bad practice
 

nahsh

New member
אז VS כנראה מקמפל כמו ++C, או שהסיומת היא cpp

כי בC סטנדרטי תקבל warning לפחות. אחרי כל תיקוני השגיאות האחרים, ואם אני מותיר את הגדרת item כמו שהייתה, אני מקבל בgcc שגיאה עבור ;p = p->next :

warning: assignment from incompatible pointer type
 

nocgod

New member
הסיומת C

וקימפלתי גם עם GCC בfreeBSD
בקיצור...זה עובד יופי טופי גם בלי לתת שמות מיותרים...רק צריך לכתוב struct ולא sturct וצריך להתייחס למערך מצביעים כמערך מצביעים ולא כמצביע
 

nahsh

New member
בכנות - הרבה שנים לא כתבתי בC.

אבל יש לי לא מעט שנות נסיון בשפה.

יכול להיות שהקומפיילרים המודרניים יותר סלחניים. יש לציין שגם בgcc קיבלתי תוכנה עובדת אחרי הwarnings. זה בוודאות לא היה ניתן בקומפיילרים ישנים. וזה שזה bad practice לא ממש שינה אם זה לא עבד בפועל.
 

nocgod

New member
לא יודע מה כתבת לו שהוא הוציא לך הערות

חבל שאתה מתווכח לריק.
הדבר היחיד שהGCC התלונן עליו היה זה שהוא עשה void main ולא לפי הסטנדרט int main.
לאחר שתיקנתי את הטעויות שלו שהכל עבר קומפילציה בלי פיפס...לגבי אם הקוד שלו עובד אני לא ערב אבל לגבי זה השאר אני בטוח ב 100 אחוזים

תשים לב שבקימפול אמרתי לו בכוח לקמפל C ושלא יחליט שום דבר על דעת עצמו + יש לך גרסא של הGCC ועל איזה מערכת הפעלה הוא רץ.
שים לב שאין שום warningים what so ever
 

nahsh

New member
הנה הקוד שבדקתי:

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

/*
wrong
typedef struct {
int num;
struct item *next;
} item;
*/


//right
typedef struct itm {
int num;
struct itm *next;
} item;


item *head;

item *createNewItem(int i) {
item *it = (item*)malloc(sizeof(item));
it->num = i;
it->next = NULL;
return it;
}

int main(int argv, char *varc[]) {

int i = 0;
item *p;
item *q;

head = createNewItem(0);
p = head;
for ( i = 1; i < 10; i++) {
q = createNewItem(i);
p->next = q;
p = q;
}

p = head;
while ( p != NULL ) {
printf("item: %d\n", p->num);
p = p->next;
}

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

return 0;
}
 

nocgod

New member
הקוד שלך שגוי

אתה משתמש בnext במבנה לפני שהגדרת אותו.

כמו שאמרתי, אני לא מתחייב לנכונות הקוד שלו, אני מתחייב שהקוד שלו מתקמפל.
 

nocgod

New member
השגיאה הזאת לא קשורה אבל לעובדה שהstruct

אנונימי.
קומפיילר C הוא one pass עד כמה שאני זוכר (בלי קשר לpre-processor) הוא מנסה להשתמש בitem לפני שהוא הגדיר אותו.
זה לא קשור בכלל לעובדה שהסטראקט אנונימי, אפילו לא קמצוץ של קשור. אתה יכול להשתמש במבנים אנונימיים בכיף גם בC של K&R.
זה שהוא לא כתב נכון את הקוד של הnode שלו ברשימה המקושרת לחוד וזה שהוא השתמש במבנה אנונימי זה לחוד.
להשתמש במבנה אנונימי כדי לייצג node (כלשהו) הוא שגוי מבסיסו כי אתה צריך קודם להגדיר את הnode כי אתה צריך להשתמש בו בתוך הגדרת הnode
מצד שני אין שום מניעה מלהשתמש במבנים אנונימיים בC.
לא יודע מה הניסיון שלך, אני מלמד C ו ++C כבר כמה שנים, מכיר את K&R בעל פה ואפילו חקרתי קצת את הסטנדרט של C ו ++C כדי למצוא הבדלים בהגדרות.
אני בטוח ב 100 אחוז שאין שום בעיה whatsoever בשימוש במבנים אנונימיים בtypedef.
 

nahsh

New member
ברור, זו לא הייתה הערה כללית

זו הייתה הערה ספציפית לקוד, שכן השתמש בitem בתוך הstruct.
 

nocgod

New member
אז שוב - אין בעיה בשימוש בstruct אנונימי

יש בעיה בזה שהשתמש בהגדרת הtypedef לפי שעשה את הtypedef בפועל.
 

BravoMan

Active member
לא בדיוק אבל בערך:

ראשית, אם רוצים ש-GCC באמת יתריע על כל מפגה סביבתי חייבם להוסיף את הפרמטר pedantic- (כי אפילו Wall- לא גורם להצמדה מלאה לסטנדרט) וגם פרמטר שמציין סטנדרט, עדיף ansi- אם מדובר בקוד לימודי.

צירוף כזה על הקוד הנתון יביא:

error: request for member ‘data’ in something not a structure or union

על השורה:

temp->data=i


אבל זה בקטנה.
הבעיה האמתית תתרחש כאשר תנסה לבצע dereference ל-next של מבנה item.

באותה מידה, יכולת לרשום שה-next הוא מטיפוס struct fu.
ב-C פשוט ניתן להניח שזה מצביע למבנה שמוגדר במקום אחר, לא משנה איך תקרא לו, כי כל עוד משתמשים בו לאחסן כתובת, מדובר באותה כמות בתים שיש להקצות.

כמובן שברגע שתנסה לגשת לתוכן של מה ש-next מצביע עליו, תקבל שגיאה נחמדה של:

error: dereferencing pointer to incomplete type


כי עכשיו צריך לדעת מה יש בפנים, ובמקרה שלנו item ו-struct item הם שני טיפוסים שונים, שאגב יכולים לחיות זה לצד זה בשלום.

וזה כבר בלי קשר לרמת הדקדוק של gcc (או כל קומפיילר אחר לצורך העניין)
 

BravoMan

Active member
נסה לקמפל את זה, ותראה איזה ברדק יוצא

(מהבחינה הלוגית)
 
למעלה