LINUX.ORG.RU

[C] typedef

 


0

0

typedef char x[2]; x p;

Изучаю С и наткнулся вот на такой typedef и меня заклинило. Не могу понять, как такое может быть. Как можно делать массив синонимом типа?

Снимите plz с ручника.

★★

А в чем проблема? Представь, что у тебя много данных подобного вида. Вполне логично выделить для них новый тип переменных.

power
()

загляни в исходники девятого плана -- там typedef очень часто используется -- повышает читабельность кода.

beastie ★★★★★
()

K&R же объясняли, что есть два направления конструирования типа данных:

1) структурой -- struct {int a; double b;} x; чтобы собирать разнородные данные в один тип.

2) массивом -- int x[2]; чтобы собирать однородные данные в один тип.

Чем должен быть массив хуже структуры по отношению к typedef?

balodja ★★★
()
Ответ на: комментарий от balodja

Я понимаю зачем нужен typedef. Но, гм.. мне непонятна семантика такого выражения.

typedef unsigned int uint;

понимаю. Сделали uint синонимом 'unsigned int'. А вот как можно массив сделать алиасом типа char (или любого другого)? Можно как-то по шагам, с ссылками на стандарт?

cruz7 ★★
() автор топика
Ответ на: комментарий от cruz7

Ты сделал x "алиасом" char[2]. Почитай еще про синтаксис объявления указателей на функции.

mannaz
()
Ответ на: комментарий от cruz7

http://flash-gordon.me.uk/ansi.c.txt

Внимательно читаем раздел 3.5.6:

In a declaration whose storage-class specifier is typedef , each
declarator defines an identifier to be a typedef name that specifies
the type specified for the identifier in the way described in $3.5.4.
A typedef declaration does not introduce a new type, only a synonym
for the type so specified.

Далее идем в 3.5.4 и находим:

3.5.4 Declarators
3.5.4.1 Pointer declarators
3.5.4.2 Array declarators
3.5.4.3 Function declarators

Any questions?

balodja ★★★
()

Скажем так, в Си много разных финтов ушами, но это не значит, что нужно пользоваться ими всеми. На деле, подобная конструкция не сильно выделяется своей читабельностью, т.е. пользоваться можешь, но лучше так не делать, за исключением когда это действительно остро необходимо. Хотя если подумать, то typedef вообще является скорее "вкусняшкой", чем каким-либо отдельно функциональным элементом.

Deleted
()
Ответ на: комментарий от Deleted

Хотя если подумать, то typedef вообще является скорее «вкусняшкой», чем каким-либо отдельно функциональным элементом.

Циклы тоже. Без них вполне можно обойтись, достаточно только if и goto.

Вот массивы действительно лучше не тайпдефить. Например,

typedef char arr[2];
arr f(const arr *v);

const86 ★★★★★
()
Ответ на: комментарий от cruz7

>>typedef char arr[2];

>>arr f(const arr *v);

>Гм.. но ведь это даже не скомпилируется.

О чём и речь. А была бы структура или простой тип под тайпдефом - скомпилировалось бы.

const86 ★★★★★
()
Ответ на: комментарий от cruz7

> >typedef char arr[2];
> >arr f(const arr *v);

> Гм.. но ведь это даже не скомпилируется.

семантика вполне понятная. почему это до сих пор не проглатывается компилятором - понятия не имею...

xydo ★★
()
Ответ на: комментарий от cruz7

>Но, гм.. мне непонятна семантика такого выражения.
ты для начала с синтаксисом typedef окончательно и полностью разберись...

xydo ★★
()

Лучше откажись от typedef где только возможно. Если тебе нужно дать другое имя типу используй #define. typedef усложняет код, что не хорошо.

golodranez ★★★★
()
Ответ на: комментарий от golodranez

> Если тебе нужно дать другое имя типу используй #define

пару примеров:

#define CHAR_PTR char*
CHAR_PTR a, b; /* bug */

typedef char CHAR_ARR[];
CHAR_ARR str = "something";

lester ★★★★
()
Ответ на: комментарий от lester

>CHAR_PTR a, b;

Не надо так делать даже в случае банального int a, b;

Лучше так:

int a;
int b;

А ещё лучше не забывать про то, что данные лучше объявлять как можно ближе к тому месту где они будут использованы.

golodranez ★★★★
()
Ответ на: комментарий от golodranez

> Не надо так делать

факт не в том что надо/не надо( для примера я так никогда и не пишу ), а в том что твой код может потом править другой человек, который не видит ничего плохого в такой записи

> А ещё лучше не забывать про то, что данные лучше объявлять как можно ближе к тому месту где они будут использованы.


спасибо, К.О. :)

lester ★★★★
()
Ответ на: комментарий от lester

>спасибо, К.О. :)

Да, я такой:)

>факт не в том что надо/не надо( для примера я так никогда и не пишу ), а в том что твой код может потом править другой человек, который не видит ничего плохого в такой записи

У меня никогда не возникало сделать #define char* char_arr и тому подобное. Так что я думаю проблемы тут нет, согласен?

golodranez ★★★★
()
Ответ на: комментарий от lester

>да я и на свои могу посмотреть, если что ;)

Да я не тебе, а скорее топик стартеру))

golodranez ★★★★
()
Ответ на: комментарий от golodranez

> А ещё лучше не забывать про то, что данные лучше объявлять как можно ближе к тому месту где они будут использованы.

А еще лучше не давать советов, которые в любом учебнике по Си приведены в разделе "глупые детские ошибки".

tailgunner ★★★★★
()
Ответ на: комментарий от golodranez

> Так что я думаю проблемы тут нет, согласен?

тут как бы имелись ввиду указатели вообще, а не char* в частности, а для них typedef используются не так уж и редко в самых разных библиотеках, думаю ты должен был с таким сталкиваться, если использовал freetype, libgd и т.д. и т.п.

lester ★★★★
()
Ответ на: комментарий от tailgunner

>А еще лучше не давать советов, которые в любом учебнике по Си приведены в разделе "глупые детские ошибки".

В моём учебнике небыло такого радездела:) а во многих книгах которые листал такой стиль был обычен , просто стиль объявления some_type var1, var2, var3; очень уж коробит:)))

golodranez ★★★★
()
Ответ на: комментарий от lester

>тут как бы имелись ввиду указатели вообще, а не char* в частности

я тоже имел это ввиду. и думаю что так делать не стоит. Хотя возможно с помощью такого приёма иногда можно скрыть излишнюю информацию.

golodranez ★★★★
()
Ответ на: комментарий от lester

>libpng, libjpeg? :)

не. с гуями, картинками, шрифтами работаю только если надо подправить их код, когда они в коммандировках :)) Хотя всегда грандиозные планы по написанию всего и вся, но семья(!).. и это хорошо:)

golodranez ★★★★
()
Ответ на: комментарий от golodranez

> с гуями, картинками, шрифтами работаю только если надо подправить их код

в каком месте вы гуй увидели? :) хотите не "гуй" - zlib, expat, loki etc.

lester ★★★★
()
Ответ на: комментарий от lester

если вы и их не использовали, то мне становится интересно - что же вы пишите и чем для этого пользуетесь? :)

lester ★★★★
()
Ответ на: комментарий от lester

Ты перечислил либы которые вообще редко используются, у нас не используються вовсе ибо даже не знаю куда их можно воткнуть для наших задач. Есть такая штука как Qt.. + glibc и ещё небольшую кучку свободных либ и прог :))

Используеться в основном в атомной промышленности(нашей и забугорной), так что бойся:) В профиле в общих словах написано. Например китайцы очень довольны качеством нашего ПО:)))

golodranez ★★★★
()
Ответ на: комментарий от golodranez

> Лучше откажись от typedef где только возможно. Если тебе нужно дать другое имя типу используй #define. typedef усложняет код, что не хорошо.

так вот кому руки с корнем до жопы отрывать надо! сделай милость -- не давай больше таких советов! не дай бог кто-то в серьёз примет. препроцессор -- это ещё то зло. лучше свести его применение к миниму, по делу и не злоупотреблять. typedef и enum очень даже вкусные штучки, позволяющие свести применение #define к нулю.

зы: не в обиду, но очень уж жестокие советы ты даёш

beastie ★★★★★
()
Ответ на: комментарий от tailgunner

в принципе да, но всё же гораздо приятней читать

Foo *
dosomething(Foo *foo, Bar *bar, ...)
{
        ...
}

вместо

struct foo *
dosomething(struct foo *foo, struct bar *bar, ...)
{
        ...
}
beastie ★★★★★
()
Ответ на: комментарий от beastie

>зы: не в обиду, но очень уж жестокие советы ты даёш

Нормальные советы. Я не призываю использовать #define везде и всюду, но для создания псевдонима типа, помоему, он лучше чем typedef. typedef, по возможности, лучше не использовать.

golodranez ★★★★
()
Ответ на: комментарий от beastie

>в принципе да, но всё же гораздо приятней читать

C++ позволяет так писать и без typedef.

golodranez ★★★★
()
Ответ на: комментарий от lester

>такая штука как Qt на этих библиотеках и основана - ft, png, zlib и т.д.

и что?:) Тебе не нужно знать на чём она основана.

golodranez ★★★★
()
Ответ на: комментарий от golodranez

> и что?:) Тебе не нужно знать на чём она основана.

а вот тебе не помешало бы знать, что практически во всех базовых библиотеках используется такой ненавистный тебе typedef( для enum, struct, ptr и т.д. ), перед тем как отсылать читать чужие исходники

lester ★★★★
()
Ответ на: комментарий от lester

как он используеться? для enum согласен.

для struct лучше не использовать, тк struct хотябы позволяет понять, что это структура иначе читать такой код затруднительно - придётся догадываться что это за тип.

пример:
struct some_type* foo(..); // понятно что функция возвращает
some_type* foo(..); // что такое some_type?

Конечно можно использоваться typedef и давать структурам приставку(для информативности) типа - st_typename. По моим наблюдениям использование обоих способов гдето 50/50. Тут дело вкуса.

для ptr даже не знаю нафиг оно надо, только для большей абстракции в редких случаях.

golodranez ★★★★
()
Ответ на: комментарий от lester

>перед тем как отсылать читать чужие исходники

ну извини, просто я удивился примеру вроде sometype var1, var2;

golodranez ★★★★
()
Ответ на: комментарий от beastie

> в принципе да, но всё же гораздо приятней читать

> Foo * dosomething(Foo *foo, Bar *bar, ...)

> struct foo *dosomething(struct foo *foo, struct bar *bar, ...)

И что в этом приятного? Без typedef по крайней мере понятно, что foo и bar - это структуры.

typedef полезен для простых типов (типа uint32_t) и указателей на функции, но не более.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Забыл ещё случаи, аналогичные FILE из libc -- т.е. когда явно противопоказано лезть грязными ручонками внутрь структуры.

kemm
()
Ответ на: комментарий от kemm

> Забыл ещё случаи, аналогичные FILE из libc --

Я и это считаю неудачным решением.

> когда явно противопоказано лезть грязными ручонками внутрь структуры.

Причем здесь typedef? Просто спрячь внутренности структуры.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Я и это считаю неудачным решением.

Почему?

> Причем здесь typedef? Просто спрячь внутренности структуры.

Тоже да. Но занафига тут пользователю библиотеки знать, структура это, объединение или вообще ХЗ что? Так, некий абстрактный тип, работать с которым можно только путём вызова определённых функций...

kemm
()
Ответ на: комментарий от kemm

>Забыл ещё случаи, аналогичные FILE из libc -- т.е. когда явно противопоказано лезть грязными ручонками внутрь структуры.

Для этого лучше подойдет указатель на незавершенный тип. К нему даже ноль прибавить нельзя.

Absurd ★★★
()
Ответ на: комментарий от Absurd

> Для этого лучше подойдет указатель на незавершенный тип. К нему даже ноль прибавить нельзя.

Ну так одно другому не мешает... Зато позволяет иметь FILE где-нибудь на какой-нибудь странной платформе не как структуру, а как какой-нибудь int, по которому унутре(с) что-нибудь индексируется, или вообще как какую-нибудь неведомую космическую @#$ню.

Имхо, подход вполне имеет право на жизнь. Но только в таком случае, да. 8))

kemm
()
Ответ на: комментарий от kemm

>> Я и это считаю неудачным решением.

> Почему?

Documentation/CodingStyle, Chaper 5. Там всё объяснят.

> Но занафига тут пользователю библиотеки знать, структура это, объединение или вообще ХЗ что?

А он это по-любому знает (в Си ты просто не можешь это спрятать). Так что это тебе вопрос - зачем ты пытаешься это прятать? Инкапсуляция ради инкапсуляции?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Documentation/CodingStyle, Chaper 5. Там всё объяснят.

Я сам люблю туда (или в style(9) от фри) тыкать любитлей тайпдефов. Но там же есть список, когда они уместны. Пункт (a) как раз про такой случай.

> А он это по-любому знает (в Си ты просто не можешь это спрятать). Так что это тебе вопрос - зачем ты пытаешься это прятать? Инкапсуляция ради инкапсуляции?

Одно дело, что он об этом с лёгкостью может узнать, другое дело -- зачем эту абсолютно ненужную ему информацию каждый раз в нос тыкать...

Ещё один довод я выше озвучил -- тут у нас SOMETYPE структура, а на соседней платформе -- int. API-то одинаков должен быть.

kemm
()
Ответ на: комментарий от kemm

> Пункт (a) как раз про такой случай.

Не совсем. struct FILE почему-то определена в заголовочном файле %)

> тут у нас SOMETYPE структура, а на соседней платформе -- int. API-то одинаков должен быть.

Указатель на структуру это вполне позволяет.

tailgunner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.