Я могу понять, как работают поинтеры с массивами, функциями и структурами, но мне неясна логика, по которой можно отделить их обозначение от указателей на переменные.
Я попробую объяснить, хотя сложно свою мешанину в голове так-то конкретизировать. Может быть, даже сам пойму.
Как я понимаю следующий листинг:
/* somewhere in main() */
typedef struct rs232_port_t port_t;
port_t* p = malloc(sizeof(p));
strncpy((*p).dev, &port_c, 3);
1. Объявляем мнимым типом (алиасом)
port_t
, истинное значение которого
struct rs232_port_t
.
2. Объявляем указатель на структуру
rs232_port_t
с идентификатором
p
.
2.1. Размечаем память размером с возврат функции измерения размера, которая берет адрес типа данных.
(Как так, разве мы его уже объявили? В моем понимании, это происходит до точки с запятой, но sizeof(p) вполне валиден.) Возврат функции разметки данных (адрес) присваеваем указателю.
3. Вызываем функцию копирования строки, которая берет параметрами адреса адресата, поставщика и размера некоего буфера, делающего неясно что, но не превышающего размеры или адресата, или поставщика. Причем, (почему?) адрес поставщика равен значению поставщика, но не данным которые он хранит. Мы не можем (почему?) передать параметр стракта в виде
p.&dev
или
*p.dev
. Верно ли, что
(p).dev
уже извлечет адрес переменной, а p является неким мета-указателем?
Верно ли я все понимаю? Можно ли как-то просто обобщить логику работы указателей и скобок? Что есть структура как тип данных, а не как контейнер типов?
Где найти нормальный мануал? Как я понял,
int *somefun (variable) = NULL;
пишется как
int (*somefun) (variable) = NULL;
для того чтобы задать порядок действий, как в математике. Но в 3тем пункте, я не могу записать
(*p).dev
как
*p.dev
. Компилятор ругается. Почему?
Почему? Почему? Почему?
Я могу писать код с моими глупыми знаниями, но из-за перфекционизма, я испытываю жутко неловкое ощущение, руководствуясь нецельной, безсистемной картиной и инструментами. И часто натыкаюсь на то что мои костыли не работают, а повторные попытки изучить сабж не помогают точно так же, как они мне уже не помогли, что заставляет сдатся.
Учебники дают именно куски знаний, но они не могут как-то систематизировать подобные конструкции языка...
Точно как они объясняют работу препроцессора.
// Это включает работу винапи, теперь можно пользоватся функциями из винапи. Удачи, я съебываю, дальше сам разбирайся, лолка.
#include <windows.h>
Вместо чего-то такого:
// Помимо определения функций, существуют и объявления.
// Они приобретают определенный смысл из-за того что существуют библиотеки, где формулируется
// частоиспользуемый программистами функционал. Например, программе может быть выгодно использовать
// библиотечную реализацию X клиента, вместо того чтобы реализовывать его самостоятельно - это упрощает
// и поддержку\сопровождение, и ускоряет разработку. Масса людей использует X клиенты, и формально - реализация
// находится в их коде, просто не компилируется в него из-за флагов, которые даны компилятору. Если не так, то как
// рограммы, реализующие в себе X-клиенты, работают? Это можно угадать, прочитая дальше.
//
// Для того чтобы обращение к таким объявленным, но общим методам было возможно:
// компилятору необходимо знать список функций, и категорезировать их на определенные и неопределенные.
//
// Определенные включаются в символьную таблицу генерируемого .o файла, и при вызове каждой функции,
// иногда: программы, выпущенные определенной реализацией компилятора; всегда: библиотеки -- будут
// искать название функции в этой символьной таблице, если эти функции нужно использовать или вызвать.
// Неопределенные, но объявленные будут специальным образом транслированы линковщику, и при линковке -
// он будет искать, в каких obj-файлах существуют необходимые определения.
//
// Так вот, .h файлы, обычно, содержат объявления функций и различных структур. По архитектурным причинам,
// предпосылки которых выше, они обязаны быть включены в любой файл, где эти функции и структуры определяются
// и\или используются.
// Препроцессор запускается до компилятора и подготавливает ему исходный код, заменяя директивы #include
// содержанием файла в двойных кавычках или угловатых скобках.
// Так и живем.
//
// Ах, да, чуть не забыл,
#include <windows.h>
Громоздкостью моего варианта пренебречь. Ну и понаписал.