LINUX.ORG.RU

[СИ] Объявление и определение переменных.

 


0

2

[СИ] Объявление и определение переменных.

Язык СИ
ОС UNIX

Иногда в СИ-программах встречается такое:


typedef struct node node;
typedef char type;
typedef node *tree;

struct node {
    int   w;
    type  val;
    node  *left;
    node  *right;
};

И это компилится и работает.
Я не понимаю таких строк. Я бы написал так:


typedef char type;

struct node {
    int   w;
    type  val;
    node  *left;
    node  *right;
};

typedef struct node node;
typedef node *tree;

Вот когда компилятор читает строку «typedef struct node node»,
то что он должен думать? Ведь node описан ниже по тексту.
Для сравнения два определения функций:

int get_matr_1(int w, int h, char matr[][w]) {...}
int get_matr_2(char matr[][w], int w, int h) {...}

Первая компилится и работает. Вторая не компилится. Видимо потому,
что w после matr[][w].
Про незавершенные структуры читал в учебнике и даже сам пользовался.
Но тут-то другое.
Какое тут правило?


Я погорячился и ошибся. Я бы написал так:

struct node {
    int   w;
    type  val;
    struct node  *left;
    struct node  *right;
};

oleg_2
() автор топика

может надо не путать С и С++?

anonymous
()

C99
6.7.2.3
109) An incomplete type may only by used when the size of an object of that type is not needed. It is not needed, for example, when a typedef name is declared to be a specifier for a structure or union, or when a pointer to or a function returning a structure or union is being declared. (See incomplete types in 6.2.5.) The specification has to be complete before such a function is called or defined.

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

Фрагмент взят отсюда
http://forum.algolist.ru/algorithm-cryptography/2337-algoritm-haffmana.html

Я просмотрел программу и не увидел ничего С++.
Кроме, разве что, описаний и bool, который я заменил на int и подумал что это
случайность.

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

bool в сях есть (#include <stdbool.h>). Кстати, удобный тип, т.к., в отличие от char, если вы сделаете bool a=5, то получите a==1, а не 5. Что иногда имеет значение.

Eddy_Em ☆☆☆☆☆
()

Кстати, вот нафига делать

typedef node *tree;
?

Это же отличный способ где-нибудь прокосячить с указателем.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от oleg_2

Это работает в С и не работает в С++, так как это разные языки

struct node {int a;};
typedef int node;
int main(int c, char** p)
{
return 0;
}
поэтому «typedef struct node node» означает введение нового имени «node» для типа «struct node».

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

Eddy_Em
Потому, что внутри функции matr обрабатывается как двухмерный массив,
и компилятору нужен размер. Я не люблю многомерные массивы, но тем не менее
это по правилам.

anonymous
Спасибо.
А верно ли я понимаю, что в последнем примере
struct node и node это разные переменные?

Eddy_Em
Это не я писал.
Прокосячение скорее всего всплывет при компиляции или опробовании.

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

внутри функции matr обрабатывается как двухмерный массив, и компилятору нужен размер

Размер и так передается. Так что двойной указатель - вполне нормальная замена. Просто чуть медленнее будет - лучше сделать одномерный массив.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от oleg_2

Не разные переменные, а типы.

Обратный пример. Работает в С++ и не работает в С.

struct node {int a;};
int main(int c, char** p)
{
	node a;
	return a.a;
}

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

anonymous
Да. Не всё, но кое-что понял. С++ я не знаю.

Eddy_Em
Согласен. Так и есть. Эти функции пробные для меньше возни.
В конечной программе массив одномерный.

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

Это просто из-за того, что в плюсах можно struct опускать. Сам на этом поначалу попадался. И еще попадался с попыткой передачи данных в функцию по ссылке.

// вот попадаются же нормальные анонимусы на ЛОРе!

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от oleg_2

Я, кстати, то ли год, то ли два назад с кем-то на спор сделал две реализации одной и той же операции с одномерным массивом и с двумерным. С двумерным вышло медленнее.

С другой стороны, если делать, как в вашем коде (т.е. не через двойной указатель, а через именно двумерный массив), то компилятор оптимизирует код и сделает обычный одномерный массив.

Eddy_Em ☆☆☆☆☆
()

постарайся каждый день уделять по 30 минут на чтение ISO/IEC 9899:1999. там есть ответы почти на все вопросы, заданные тобой на лоре…

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