PDA

View Full Version : راهنمایی یک کد



cyber_17
یک شنبه 14 دی 1393, 15:29 عصر
سلام
دوستان تو کد زیر که تعریف یک Linked List هست، چرا تو خط دوم از typedef استفاده کرده؟ خط اول رو متوجه شدم اما دوم رو نه.

127239

zero_ox
یک شنبه 14 دی 1393, 19:05 عصر
سلام با این شیوه که نوشته حتما ارور می ده می تونی کد زیر رو امتحان کنی من نمی دونم این عکس رو ازچه کتابی گرفتی مثل اینکه بنده خدا قصد داشته مخاطب رو حسابی گیچ کنه .. شیوه صحیح رومی تونی تو لینک های زیر ببینی


#include <stdio.h>
#include <stdlib.h>
typedef struct NODE *P_NODE;
typedef struct NODE{
char name[21];
int num;
P_NODE link;
};
int main()
{
NODE c;


return 0;
}




http://en.wikipedia.org/wiki/Struct_(C_programming_language)

http://en.wikipedia.org/wiki/Typedef

cyber_17
یک شنبه 14 دی 1393, 20:50 عصر
خدا خیرتون بده کلی باهاش کلنجار رفتم اصلا نمیفهمیدمش. اجازه بدید اسمشو نگم که آبروی یکی از اساتید معروف (آکادمیک) نره!! البته تو این کتاب اشتباهات دیگه هم پیدا کردم.
بله اصلا اجرا نمیشه.

در واقع درستشو به شکل زیر میشه نوشت. درسته؟ میتونیم point رو به عنوان نام مستعار برای struct NODE در نظر بگیریم؟


#include <stdio.h>
#include <stdlib.h>
typedef struct NODE *P_NODE;
typedef struct NODE{
int num;
P_NODE link;
}point;
int main()
{
point c;
c.num=21;
c.link="null";
printf("%d",c.num) ;
}

rahnema1
یک شنبه 14 دی 1393, 22:37 عصر
اینجا دو مورد داریم که هیچ کدام در زبان c اشتباه سینتکسی محسوب نمی شه.
مورد اول که در اون کتاب اومده

typedef struct NODE{
char name[21];
int num;
P_NODE link;
};

اینجا در زبان c اشکالی از لحاظ سینتکس وجود نداره اما اون typedef عملا بی تاثیره
در حالیکه در زبان ++c این نحوه اعلان خطای سینتکس محسوب میشه
موردی که شما point را به عنوان نام مستعار معرفی کردید درسته اما اشکالی که وجود داره اینه که به جای NULL از "null" استفاده کردید. NULL در واقع صفر هست اما "null" آدرس n یعنی حرف اول کلمه را به c.link میفرسته

omid_kma
یک شنبه 14 دی 1393, 23:08 عصر
در حالیکه در زبان ++c این نحوه اعلان خطای سینتکس محسوب میشه

البته در ++C هم خطای سینتکس نیست .
داخل GCC (http://coliru.stacked-crooked.com/a/9fb93e3ca2ea42ef) , CLANG (http://coliru.stacked-crooked.com/a/59d3c9db1e3237fe) فقط وارنینگ داده میشه ویژوال استودیو هم بدون وارنینگ کد رو اجرا می کنه.
گذاشتن typedef در ++C قبل از struct کاربردی نداره ولی در C برای تعریف متغیر مجبور بودید جتما واژه typedef رو قبل از struct بزارید .(البته به اون شکلی که کتاب استفاده کرده کاربردی نداره)


اسمشو نگم که آبروی یکی از اساتید معروف (آکادمیک) نره!!

کتاب جعفر نژاد قمی نیست ؟:))
در کل بنظر من کتابی که این جور کدی داخلش هست ارزش خوندن نداره .

rahnema1
دوشنبه 15 دی 1393, 14:33 عصر
البته در ++C هم خطای سینتکس نیست .
مثلا در بورلند 5.5 در مورد ++c خطا ایجاد میشه اما در مورد c خطا نمیده .
فکر کنم در هر دو زبان خطا باشه چون typedef دو تا بخش داره و استاندارد هر دو هم گفته دو بخشه. نمیدونم کامپایلرها چرا فقط هشدار میدن :متفکر:

omid_kma
دوشنبه 15 دی 1393, 15:19 عصر
مثلا در بورلند 5.5 در مورد ++c خطا ایجاد میشه اما در مورد c خطا نمیده .
فکر کنم در هر دو زبان خطا باشه چون typedef دو تا بخش داره و استاندارد هر دو هم گفته دو بخشه. نمیدونم کامپایلرها چرا فقط هشدار میدن :متفکر:

من استاندارد رو نگاه کردم چیزی پیدا نکردم که گفته باشه حتما باید اسم هم گذاشته بشه .
احتمالا بخاطر این هست که اکثر کامپایلر ها typedef type رو به عنوان یک token در نظر میگیرن و مثل int ; که فقط وارنینگ داده میشه typedef هم همین طوره .

rahnema1
دوشنبه 15 دی 1393, 16:39 عصر
من استاندارد رو نگاه کردم چیزی پیدا نکردم که گفته باشه حتما باید اسم هم گذاشته بشه .
احتمالا بخاطر این هست که اکثر کامپایلر ها typedef type رو به عنوان یک token در نظر میگیرن و مثل int ; که فقط وارنینگ داده میشه typedef هم همین طوره .

در استانداد ++c در بخش 7.1.3 این اومده:
Declarations containing the decl-specifier typedef declare identifiers that can be used later for naming fundamental (3.9.1) or compound (3.9.2) types.
که identifiers دقیقا به معنای اسمه
باز در استاندارد سی n1570 ص 137 کلمه identifier به کار رفته
فکر کنم ;int هم اشتباهه چون یک اعلان لازمه حداقل یک اسم را معرفی کنه یا یک اسم قبلی را اعلان کنه
اما empty declaration را استاندارد ++c تعریف کرده که فقط از ; تشکیل شده
:متفکر:

omid_kma
دوشنبه 15 دی 1393, 18:59 عصر
در استانداد ++c در بخش 7.1.3 این اومده:
Declarations containing the decl-specifier
typedef declare identifiers that can be used later for naming fundamental (3.9.1) or compound (3.9.2) types.
که identifiers دقیقا به معنای اسمه

ببینید این جمله اینو میگه : تعریف هایی شامل typedef اسم هایی معرفی می کنند که برای ..... استفاده میشوند.
منظور من از اسم چیزی هست که جلوی type گذاشته میشه (typedef type name) عبارت بالا حرفی در این مورد نزده .


فکر کنم ;int هم اشتباهه چون یک اعلان لازمه حداقل یک اسم را معرفی کنه یا یک اسم قبلی را اعلان کنه

آره همین طوره بنابه تعریف declration :


3.1 Declarations and definitions
A declaration (Clause 7) may introduce one or more names into a translation unit or redeclare names
introduced by previous declarations.

به عبارتی declration گفته میشه که یک اسم یا بیشتر از یک اسم رو معرفی کنه . پس typedef type; و همین طور int ; جزو declration ها بحساب نمیان.

ولی نمیشه این نتیجه رو گرفت : چون typedef type یک declration نیست پس صحیح نیست . از A-->B نمیشه نتیجه گرفت a] ~A-->~B]

cyber_17
دوشنبه 15 دی 1393, 19:19 عصر
اینجا دو مورد داریم که هیچ کدام در زبان c اشتباه سینتکسی محسوب نمی شه.
مورد اول که در اون کتاب اومده

typedef struct NODE{
char name[21];
int num;
P_NODE link;
};

اینجا در زبان c اشکالی از لحاظ سینتکس وجود نداره اما اون typedef عملا بی تاثیره

اما من دقیقا توی c اجرا کردم و ارور داد (اجرا نشد). من این کد رو در c و تو لینوکس با کامپایلر GCC اجرا کردم نشد:

#include <stdio.h>#include <stdlib.h>
typedef struct NODE *P_NODE;
typedef struct NODE{
char name[21];
int num;
P_NODE link;
};
int main()
{
NODE c;
c.num=15;
printf("%d" , c.num);


return 0;
}


در حالی که با اصلاح اون ارور، کد زیر رو زدم و بدون خطا کامپایل و اجرا شد:

#include <stdio.h>#include <stdlib.h>
typedef struct NODE *P_NODE;
typedef struct NODE{
char name[21];
int num;
P_NODE link;
}point;
int main()
{
point c;
c.num=15;
printf("%d" , c.num);


return 0;
}




در حالیکه در زبان ++c این نحوه اعلان خطای سینتکس محسوب میشه

اما دقیقا کد اولیه رو تو C++‎‎‎‎‎‎‎‎‎‎ زدم (با همون کامپایلر) و اروری نداد و اجرا شد اما warning داد. اینم کدش:

#include <iostream>using namespace std;
typedef struct NODE *P_NODE;
typedef struct NODE{
char name[21];
int num;
P_NODE link;
};
int main()
{
NODE c;
c.num=15;
cout << c.num;


return 0;
}



اما همون طور که گفتم هشدار زیر رو داد:‌
Description Resource Path Location Type‘typedef’ was ignored in this declaration [enabled by default] C++‎‎‎‎‎‎‎‎‎‎.cpp /C++‎‎‎‎‎‎‎‎‎‎/src line 8 C/C++‎‎‎‎‎‎‎‎‎‎ Problem


و حالا نکته ای هم که برام جالب بود این بود که C++‎‎‎‎‎‎‎‎‎‎ به خاطر خط NODE c; هم هیچ وارنینگی نداد. چون اگه حواسم بود اول struct NODE c; می نوشتم ولی بعد دیدم بدون مشکل اجرا کرد! چون معمولا تو C این کار ایراد داره.

و وقتی به کد زیر اصلاح کردم بدون خطا اجرا:

#include <iostream>
using namespace std;
typedef struct NODE *P_NODE;
typedef struct NODE{
char name[21];
int num;
P_NODE link;
}point;
int main()
{
point c;
c.num=15;
cout << c.num;


return 0;
}





موردی که شما point را به عنوان نام مستعار معرفی کردید درسته اما اشکالی که وجود داره اینه که به جای NULL از "null" استفاده کردید. NULL در واقع صفر هست اما "null" آدرس n یعنی حرف اول کلمه را به c.link میفرسته

بله کاملا حق با شماس اصلا حواسم نبود نکته خوبی رو گوشزد کردید.

cyber_17
دوشنبه 15 دی 1393, 19:29 عصر
البته در ++C هم خطای سینتکس نیست .

کتاب جعفر نژاد قمی نیست ؟:))
در کل بنظر من کتابی که این جور کدی داخلش هست ارزش خوندن نداره .

نخیر جعفرنژاد نیست (; بازم جعفرنژاد (:
کتاب برنامه نویسی نیست ساختمان دادس

omid_kma
دوشنبه 15 دی 1393, 19:32 عصر
اما من دقیقا توی c اجرا کردم و ارور داد (اجرا نشد). من این کد رو در c و تو لینوکس با کامپایلر GCC اجرا کردم نشد:



و حالا نکته ای هم که برام جالب بود این بود که C++‎‎‎‎‎‎‎‎ به خاطر خط NODE c; هم هیچ وارنینگی نداد. چون اگه حواسم بود اول struct NODE c; می نوشتم ولی بعد دیدم بدون مشکل اجرا کرد! چون معمولا تو C این کار ایراد نداره.
درC زمان تعریف متغیر از نوع struct باید از کلمه struct استفاده کنید ولی در ++C نیاز به این کار نیست .

cyber_17
دوشنبه 15 دی 1393, 19:39 عصر
اما در کل فارق از نوع تعریف استاندارد c و c++ به نظرم، کار بیهوده ایه که typedef گذاشته بشه بدون دادن اسم.. کد رو کثیف می کنه.. همینطور int ;
جمله typedef declare identifiers that can be used later for naming fundamental (3.9.1) or compound (3.9.2) types هم دقیقا داره کاربرد درست typedef رو میگه در صورتی که اگه به اون شکل که بیان شد (اسم نذاشتن) درست بود خب اون رو هم ذکر می کرد تو استاندارد.
ممنون از دوستان

cyber_17
دوشنبه 15 دی 1393, 19:50 عصر
درC زمان تعریف متغیر از نوع struct باید از کلمه struct استفاده کنید ولی در ++C نیاز به این کار نیست .

بله من منظورم این بود معمولا تو C این کار ایراد داره که نوشتم نداره. اصلاح کردم. اما همه اینا به کامپایلر هم بستگی داره من تو c هم نذاشتم و ایرادی هم نگرفت اما در اصل تو c باید گذاشت.

rahnema1
دوشنبه 15 دی 1393, 20:36 عصر
ببینید این جمله اینو میگه : تعریف هایی شامل typedef اسم هایی معرفی می کنند که برای ..... استفاده میشوند.
منظور من از اسم چیزی هست که جلوی type گذاشته میشه (typedef type name) عبارت بالا حرفی در این مورد نزده .
منظور من هم همین هست . حالا یه سوال: بالاخره باید یک identifier معرفی کنه. اون identifier چیه؟ type که نمیتونه باشه پس منظور از identifier همون name هست



به عبارتی declration گفته میشه که یک اسم یا بیشتر از یک اسم رو معرفی کنه . پس typedef type; و همین طور int ; جزو declration ها بحساب نمیان.
نشد دیگه! typedef یک specifier محسوب میشه و هیچ کاربردی نداره مگر اینکه در یک declaration استفاده بشه
و این نحوه نوشتن int فقط در declaration کاربرد داره
بنابراین وقتی بنویسیم typedef type خطای قطعی به خاطر استفاده نادرست typedef هست چون یک identifier معرفی نمیشه و type مثلا اگه int باشه باتوجه به این قاعده که در این declaration یک اسم معرفی نمیشه هم میشه خطای سینتکس گرفت
نمیشه که هر کلمه را هر جا گذاشت

rahnema1
دوشنبه 15 دی 1393, 20:41 عصر
اما من دقیقا توی c اجرا کردم و ارور داد (اجرا نشد). من این کد رو در c و تو لینوکس با کامپایلر GCC اجرا کردم نشد:

گفتم خطای سینتکس نداره بلکه خطای منطقی داره
اگر چه بعدا به این نتیجه رسیدم هم خطای سینتکس داره هم خطای منطقی
کامپایلرها هم لزوما به طور دقیق مطابق استاندارد عمل نمی کنند یک موردش به نظر من همینه

omid_kma
دوشنبه 15 دی 1393, 20:50 عصر
نشد دیگه! typedef یک specifier محسوب میشه و هیچ کاربردی نداره مگر اینکه در یک declaration استفاده بشه
و این نحوه نوشتن int فقط در declaration کاربرد داره

اگر جایی از استاندارد گفته شده که این نحوه نوشتن int فقط در declration کاربرد داره و "typedef فقط باید در declration استفاده بشه" ذکر کنید وگرنه این چیزیه که فقط فکر می کنید درسته ولی استاندارد دربارش حرفی نزده . قرار نیست که درباره مطالبی که فقط فکر می کنیم درسته بحث کنیم .


نمیشه که هر کلمه را هر جا گذاشت

چیزی که داخل استاندارد ذکر نشده implementation-defined هست شاید خطا نگرفتن typedef type; باعث بشه مرحله parse کردن کد سریع تر انجام بشه پس کاری که gcc , clang انجام دادن از نظر من ایرادی نداره .

rahnema1
دوشنبه 15 دی 1393, 21:05 عصر
اگر جایی از استاندارد گفته شده که این نحوه نوشتن int فقط در declration کاربرد داره و "typedef فقط باید در declration استفاده بشه" ذکر کنید وگرنه این چیزیه که فقط فکر می کنید درسته ولی استاندارد دربارش حرفی نزده . قرار نیست که درباره مطالبی که فقط فکر می کنیم درسته بحث کنیم .
اگه شما هر کلمه را هر جا دلتون خواست بذارید و استاندارد هم در اون مورد حرفی نزده بگید کاری که انجام دادم درسته؟؟
در استاندارد نحوه declaratio را گفته و همچنین گفته که میشه در declaration از specifier استفاده کرد
typedef ذیل قسمت specifier ها و گفته در declaration استفاده میشه که تمام اینها در فصل declaration اومده


چیزی که داخل استاندارد ذکر نشده implementation-defined هست شاید خطا نگرفتن typedef type; باعث بشه مرحله parse کردن کد سریع تر انجام بشه پس کاری که gcc , clang انجام دادن از نظر من ایرادی نداره .
موراد implementation-defined دقیقا در استاندارد ذکر شده حتی در فهرست هم نام اونها هست
موراد اختیاری با opt مشخص شده
اگه هر چی را هر جا دلمون خواست بذاریم یک اتفاق می افته که همون خطای سینتکسه! :چشمک:

zero_ox
دوشنبه 15 دی 1393, 21:31 عصر
این لینک هم ببینیدhttp://gotoanswer.stanford.edu/?q=typedef+struct++in+c%2B%2B+

omid_kma
دوشنبه 15 دی 1393, 21:40 عصر
اگه شما هر کلمه را هر جا دلتون خواست بذارید و استاندارد هم در اون مورد حرفی نزده بگید کاری که انجام دادم درسته؟؟

اول این که هر کلمه رو نمیشه استفاده کرد چون کلمه های کلیدی داخل استاندارد ذکر شدند . محلی هم که این کلمات می تونن قرار بگیرن هم ذکر شده . پس آره اگر چیزی ذکر نشده باشه من دلیلی نمی بینم که استفاده ازش درست نباشه .



در استاندارد نحوه declaratio را گفته و همچنین گفته که میشه در declaration از specifier استفاده کرد

دقیقا این گفته شده :

7.1 Specifiers [dcl.spec]
1 The specifiers that can be used in a declaration are

واژه can معنی حتما باید فلان جا استفاده بشه رو نمیده .


typedef ذیل قسمت specifier ها و گفته در declaration استفاده میشه که تمام اینها در فصل declaration اومده

آره گفته در declration استفاده می شه ولی ذکر نکرده که دیگه جاهای دیگه نباید استفاده بشه .


موراد implementation-defined دقیقا در استاندارد ذکر شده حتی در فهرست هم نام اونها هست

آره درسته ولی یک تعریف هم داریم به این شکل :

3.4.3 1 undefined behavior behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements
پس آیا میشه گفت typedef type جزو undefine behaviour ها هست ؟
مثلا من فرضا یک کامپایلر ++C نوشتم بعد امدم typedef type ; رو برای این کار رزرو کردم که بیاد مثلا یک enum رو به یک کلاس تبدیل کنه !

enum class A{B,D};
typedef A;//khodkar A ro tabdil kon be class

این مورد undefine behaviour هست پس پیاده سازی من میشه implementation-defined-behaviour
آیا جایی از استاندارد هست که گفته باشه این کار اشتباه هستش؟!!

بنظر من عباراتی که ذکر شده باید صریح تر باشه .

rahnema1
دوشنبه 15 دی 1393, 21:54 عصر
آره گفته در declration استفاده می شه ولی ذکر نکرده که دیگه جاهای دیگه نباید استفاده بشه .
مشکل همینه استاندارد نحوه استفاده را گفته و وظیفه typedef را گفته و اگه مطابق اون رفتار نشه می گیم خطای سینتکس



پس آیا میشه گفت typedef type جزو undefine behaviour ها هست ؟

imposes no requirements دقیقا به همین اشاره می کنه در صورتی که typedef وظیفه اش مشخص شده و requirement اون تعیین شده


مثلا من فرضا یک کامپایلر ++C نوشتم بعد امدم typedef type ; رو برای این کار رزرو کردم که بیاد مثلا یک enum رو به یک کلاس تبدیل کنه !
شما یک خطای سینتکس را می خواهید ازش یه استفاده دیگه کنید. با این کار مخالف استاندارد عمل کردید

omid_kma
دوشنبه 15 دی 1393, 22:02 عصر
مشکل همینه استاندارد نحوه استفاده را گفته و وظیفه typedef را گفته و اگه مطابق اون رفتار نشه می گیم خطای سینتکس

آخه مشکل این جاست که تا اون جایی که می دونم syntax error هم تعریف دقیقی در استاندارد نداره !


imposes no requirements دقیقا به همین اشاره می کنه در صورتی که typedef وظیفه اش مشخص شده و requirement اون تعیین شده
نه اصلا منظور این نبوده .
معنی اون جمله این هست که :
استاندارد برای
use of a nonportable or erroneous program construct or erroneous data هیچ ضرورتی تحمیل نمی کند .
اون چیزی که شما گفتید ذکر نشده.
و به نظر من typedef type اینجا nonportable میشه پس undefined behavior هست .