инициализация структуры - PullRequest
4 голосов
/ 05 июня 2010

gcc 4.4.4 c89

Я буду добавлять в этот список. Так что я ищу, чтобы NULL прекратить это. Тем не менее, я получаю предупреждение: "Initialization makes integer from pointer without a cast"

Почему в нем упоминается целое число, если я не использовал в этой структуре?

Я думал в этом случае массивы и указатели, где же?

 struct company_prof
    {
        char name[32];
        size_t age;
        char position[32];
    } employee[] = {
        { "Job Bloggs",  23, "software engineer"    },
        { "Lisa Low" ,   34, "Telecomms Technician" },
        { "simon smith", 38, "personal assistist"   },
        { NULL         , -1, NULL                   }
    };

Большое спасибо за любые предложения,

Ответы [ 3 ]

5 голосов
/ 05 июня 2010

Вы пытаетесь инициализировать массив символов с помощью NULL. Это не имеет никакого смысла. Например, вы получите то же предупреждение от

char a[100] = { NULL };

и это не имеет смысла точно так же.

"Целое число", упомянутое в диагностическом сообщении, является первым элементом массива символов. char - это целочисленный тип в C, и когда вы пишете

char a[100] = { NULL };

это попытка инициализировать 0-й элемент массива a с помощью NULL. На вашей платформе NULL объявляется как нечто с типом указателя, поэтому диагностическое сообщение говорит, что вы пытаетесь сделать целое число (a[0]) из указателя (NULL) без приведения.

Еще более простой пример может выглядеть следующим образом

char c = NULL;

и по тем же причинам вам выдаст такое же диагностическое сообщение.

Могу я спросить, почему вы пытаетесь инициализировать char с NULL? Каково было ваше намерение?

Если вы не собираетесь записывать в массивы name и position после инициализации, возможно, вам следует использовать указатели вместо массивов, как в

struct company_prof
    {
        const char *name;
        size_t age;
        const char *position;
    } employee[] = {
        { "Job Bloggs",  23, "software engineer"    },
        { "Lisa Low" ,   34, "Telecomms Technician" },
        { "simon smith", 38, "personal assistist"   },
        { NULL         , -1, NULL                   }
    };

Формально, в этом случае NULL имеет смысл. Но не в случае массива.

Но менее формально цель этой записи { NULL, -1, NULL } в конце массива мне не ясна. Является ли какой-нибудь завершающий элемент? Почему бы вам просто не использовать точный размер массива вместо создания завершающего элемента?

5 голосов
/ 05 июня 2010

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

Причина, по которой вы получаете бит о преобразовании, состоит в том, что символы (например, name[0]) представляют собой маленькие целые числа, и он пытается вставить указатель NULL в первый символ каждой строки. Этот первый символ слишком мал, чтобы удерживать указатель, поэтому он предупреждает вас об этом.

Вы, вероятно, хотите использовать "\0" вместо NULL здесь. Это пустая строка или пустая строка, которая немного отличается от нулевого указателя.

Редактировать : Альтернативой, которую вы могли бы рассмотреть для получения размера списка, является не использование значения часового, а определение константы, которая вычисляет его по размерам в байтах. Типичная конструкция для этого выглядит так:

static const int num_employees = sizeof(employee) / sizeof(employee[0]);
1 голос
/ 05 июня 2010

Вы используете char [32] в качестве членов структуры. Вы не можете конвертировать из NULL в символ [N]. Так что происходит, что NULL рассматривается как ноль. Предупреждение приходит от компилятора, решившего преобразовать NULL в 0. Поскольку инициализация char [N] происходит внутри массива, инициализирующего его в 0, действительна, он просто устанавливает все значения в ноль. например,

struct wrapper {char i [2]} w = {0}

установит для внутреннего i значение {0,0}

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

|==============name============||--||==========position===========|
0123456789012345678901234567890101230123456789012345678901245678901
Job.Bloggs0000000000000000000000(23)software.engineer00000000000000 // first
...                                                                 // rest
00000000000000000000000000000000(-1)0000000000000000000000000000000 // sentinel

Это может или не может быть тем, что вы хотите ... но это означает, что зацикливание на этих значениях не будет тем, что вы можете ожидать: в частности, это не будет работать:

p = employee;
while( p.name != NULL )
{
  printf("%s", p.name);
  ++p;
};

Это просто приведет к распечатке мусора из памяти и в конечном итоге к segfault.

Вместо этого вы можете попробовать что-то подобное

p = employee;
while( p.name[0] != 0 )
{
  printf("%s", p.name);
  ++p;
};

Но это не будет работать для имен типа "\ 0foo" (которые вы все равно можете считать недействительными ...)

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