* является незаконным для структуры? - PullRequest
4 голосов
/ 26 октября 2009

Я пытался скомпилировать следующий код, но компилятор этого не сделал, потому что «* недопустимо для структуры» - это правда?

struct String {
    int length;
    int capacity;
    unsigned check;
    char ptr[0];
} String;

void main(){

    char *s;
    String *new_string = malloc(sizeof(String) + 10 + 1);

}

Ответы [ 8 ]

21 голосов
/ 26 октября 2009

Либо используйте typedef:

typedef struct String {
    int length;
    int capacity;
    unsigned check;
    char ptr[0];
} String;    /* now String is a type */

Или прямо сказать struct String:

void main(){
    char *s;
    struct String *new_string = malloc(sizeof(struct String) + 10 + 1);
}
18 голосов
/ 26 октября 2009

Поскольку никто, кажется, еще не упомянул об этом, позвольте мне объяснить, что на самом деле означает код , который вы использовали.

То, что вы использовали, является своего рода сокращенной записью, которая определяет структуру , а также создает переменную. Это эквивалентно:

struct String {
    int length;
    int capacity;
    unsigned check;
    char ptr[0];
};
struct String String; //creates a global variable of type "struct String"

Позже,

String *new_string

не удается скомпилировать, потому что нет имени типа с именем «String» (только для «struct String». Существует глобальная переменная с именем «String», но это не имеет смысла в этом выражении.

5 голосов
/ 26 октября 2009

Вы забыли typedef:

typedef struct String {
    int length;
    int capacity;
    unsigned check;
    char ptr[0];
} String;
/* String is now a type, not an object */

void main(){

    char *s;
    String *new_string = malloc(sizeof(String) + 10 + 1);
}
3 голосов
/ 26 октября 2009

Да, это правда. Двоичный оператор * (умножение) применим только к арифметическим типам. В вашем примере вы объявили переменную Struct типа struct Struct и затем попытались ее умножить на что-то. Это просто не имеет никакого смысла. Вы не можете умножить структурные объекты. Это то, что говорит вам компилятор.

Дополнительно: 1. Это int main, а не void main. 2. Язык C не поддерживает объявления массива с размером 0. Возможно, вы захотите изменить объявление массива внутри вашего типа структуры.

2 голосов
/ 26 октября 2009

Попробуйте:

 typedef struct String_t {
        int length;
        int capacity;
        unsigned check;
        char ptr[0];
    } String;

Ваш не совсем объявляет такой тип. Более конкретно, он скрывает ваш тип, вводя переменную с тем же именем. И это приводит в замешательство компилятор ...:)

2 голосов
/ 26 октября 2009

используйте этот код:

struct String* new_string = malloc(sizeof(String)+10+1);

Вы также можете рассмотреть typedef

typedef struct String sString;

позволит вам использовать ваш фрагмент:

sString* mystring
0 голосов
/ 26 октября 2009

Как писал ранее Артелиус, ваше определение структуры, скорее всего, не то, что вам нужно. Самым простым решением будет:

#include <stdlib.h>

struct String {
    int length;
    int capacity;
    unsigned check;
    char ptr[0];
};

int main(){
    char *s;
    String *new_string = (String*)malloc(sizeof(String) + 10 + 1);
    return 0;
}

На самом деле это тоже компилируется, когда я тестировал как gcc, так и g ++. Если вы действительно делаете C ++, как подразумевают ваши теги, вам лучше включить cstdlib вместо stdlib.h или сделать это правильно (tm) и превратить вашу строку в класс и использовать new.

0 голосов
/ 26 октября 2009

Редактировать: Теперь я вижу, что исходный вопрос был помечен C, а не C++, и кто-то ошибочно пометил его C++ (отменил пометку).


Одним из решений, как уже упоминалось, является добавление typedef до объявления struct, однако, поскольку это C++ (в соответствии с тегом вопроса), а не C, более идиоматичным и более коротким способом будет просто бросить висячую "Струну"

struct String {
    int length;
    int capacity;
    unsigned check;
    char ptr[0];
};

Этого достаточно, чтобы ввести тип с именем String, причина, по которой исходный код не работал, заключалась в том, что в дополнение к введению типа с именем String вы ввели переменную с именем String, которая скрывала тип.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...