LINUX.ORG.RU

Кто хорошо знает С?


0

1

Кто хорошо знает С по полочкам разложите что сие код делает:

#define container_of(ptr, type, member) ({                      \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})

Больше всего меня интересует два вопроса: 1 - как понимать нуль при обращении к члену структуры (подразумевается что type есть некая структура) 2 - как блок {} может возвращать какое либо значение (или я чего не догоняю)

Ответ на: комментарий от rg-400

затупил :) типа тут это определенная тобой структура т.е. передается например struct mystruct

rg-400
()

Предполагается, что в структуре type есть поле member любого типа. typeof( ((type *)0)->member ) - таким образом «подставляется» его тип: через махинации с приведением типов «создается» фейковый указатель на type и через него получается доступ к члену member; так как gcc прогоняет это на стадии компиляции, никакой ошибки доступа к данным по нулевому адресу не происходит (потому что как такового обращения к данным нет, производится лишь анализ типа).

({)} - это gcc-изм, некий блок, из которого «возвращается» значение последнего выражения, в данном случае - какая-то разница между указателями.

staseg ★★★★★
()
Ответ на: комментарий от rg-400

Зачем это: У тебя есть указатель на поле структуры, а ты получишь указатель на начало структуры.

rg-400
()
Ответ на: комментарий от arsi

1 - т. е. ((struct my_struct *)0)->field1 это что за хрень такая и как её переваривать совсем не понимаю (меня ноль в ступор вводит)?

2 - В gcc {} возвращает значение последнего положения в ней, так?

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

>typeof( ((type *)0)->member ) Тут написано именно то, что написано: «тип члена member структуры типа type».

Выражение под typeof не компилируется, а только анализируется компилятором на предмет определения типа. Считай typeof таким хитрым макросом, подставляющим вместо себя в исходник имя типа своего аргумента (хотя это не макрос нифига, разумеется).

Выражение ((type *)0)->member приводит 0 указазателю на type. (А 0 всегда можно привести к любому указателю.) А потом просто берётся тип его поля member.

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

В чём причина шока? В коде всё понятно и наглядно. Комментарии не требуются.

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

>простите что значит «фейковый»?

fake...

Смотри. (type*)0 - так ты как бы создаешь указатель type* =0. Это указатель на структуру с нулевым адресом. ((type*)0)->member - дотягиваешься до члена этой структуры. Оборачиваешь это выражение в typeof и узнаешь тип члена member структуры типа type.

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

В памяти структура лежит как один блок, а обращение к полю(.) вычисляет смещение т.е. адрес начала + какое-то число байт = получаем адрес поля. если начальный адрес 0, то зная адрес поля структуры и кол-во байтов до начала можем получить адрес структуры. А кол-во байтов получить просто мы берем (unsigned long)&((struct mystruct*)0)->field) == кол-во байтов.

rg-400
()

Так пишут только пидарасы - забей и не пиши так никогда!

anonymous
()

Стандартный макрос, я такое видел, например, в list.h из ведра линуха. У gcc, на сколько знаю, есть built-in реализация container_of и offset_of.

Тут-то всё более-менее понятно, но, увы, есть места сильно сложнее, я из-за них C недолюбливаю потому что я их не понимаю.

true_admin ★★★★★
()
typeof( ((type *)0)->member )

-- тип члена member структуры типа type

typeof( ((type *)0)->member ) *__mptr = (ptr);

-- объявить указатель на переменную типа члена member

(type *)( (char *)__mptr - offsetof(type,member) );

-- указатель на начало структуры типа type.

Другими словами

struct my_type{
        int start;
        int end;
} x;

int *ptr = &x.end;

Тогда

container_of(ptr, my_type, end) == &x;

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

Пруф?
Мне всегда казалось, что для таких целей существует оператор ",", который ещё из K&R.

anonymous
()

товарищи, помогите с округлением, плиз

хочу округлялку вот такого вида:

33 = 33
931 = 931
1023 = 0.99k
1127 = 1.1k
27051 = 26.4k

наваял тут г-внокод http://paste.pocoo.org/show/306192/ но он мне не нравится.

есть ли уже такое готовое библиотечное?

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

это всё я затеял чтоб в nginx autiondex такое округление было

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

> Мне всегда казалось, что для таких целей существует оператор ",", который ещё из K&R.

В кругло-фигурные скобочки можно запихать цикл, свич, ифы и приправить парочкой гото. Запятая не даст вам такого набора радостей.

С C99 я всё-таки промахнулся. Приснилось, наверное.

const86 ★★★★★
()

Кто хорошо знает С?

Ну, наверное, кто-нибудь из комитета стандартизации, а что?

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