Можете ли вы дать информацию о том, почему хранится значение переменной, но размер структуры по-прежнему равен 0 байтов? - PullRequest
0 голосов
/ 04 июля 2018

Почему структурная переменная 'e' не имеет размера, а ее элемент объявлен и инициализирован?

#include <stdio.h>

int main ()
{
  struct e1
  {
    int a[0];
  };
  struct e1 e;
  e.a[0] = 2;
  printf ("%d\n", e.a[0]);
  printf ("%d", sizeof (e));
}

Выход
2
0

Ответы [ 4 ]

0 голосов
/ 04 июля 2018

в вашем случае это вызывает неопределенное поведение. Но очень похожие структуры используются, если вы добавляете некоторые данные, которые были сохранены в структуре, но их размер неизвестен. Но, конечно, вам нужно выделить место для этого

Пример:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct
{
    size_t size;
    char string[];
}string;

string *String(void)
{
    string *s = malloc(sizeof(string));
    if(s) s -> size = 0;
    return s;
}

string *StringCopy(string *dest, const string *src)
{
    if(!src || !dest) return NULL;
    if(dest -> size < src -> size)
    {
        dest = realloc(dest, src -> size + sizeof(string));
        if(!dest) return NULL;
    }
    memcpy(dest -> string, src -> string, src -> size);
    dest -> size = src -> size;
    return dest;
}

string *StringCstringCopy(string *dest, const char *src)
{
    size_t srcLength;
    if(!src || !dest) return NULL;

    srcLength = strlen(src);
    if(dest -> size < srcLength)
    {
        dest = realloc(dest, srcLength + sizeof(string));
        if(!dest) return NULL;
    }
    memcpy(dest -> string, src, srvLength);
    dest -> size = srcLength;
    return dest;
}


int main(void) {

    string *s = String();

    s = StringCstringCopy(s, "Hello");
    // your code goes here
    return 0;
}
0 голосов
/ 04 июля 2018

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

Что нужно помнить сейчас: C никогда не проверяет наличие ошибок, подобных этой, он просто объявляет поведение неопределенным. Будьте осторожны при программировании на C.

Примечание: массив или структура нулевого размера даже не существует в стандартном C, поэтому ваш компилятор также может отклонить этот код.

0 голосов
/ 04 июля 2018

Ваш код недействителен C . Массив не может иметь нулевой размер.

Цитата C11, глава

Если размер является выражением, которое не является целочисленным константным выражением: если это происходит в объявление в области действия прототипа функции, оно обрабатывается так, как если бы оно было заменено на *; в противном случае, каждый раз, когда он оценивается, он должен иметь значение больше нуля.

Учитывая, что ваш компилятор поддерживает массив нулевой длины в качестве последнего элемента структуры, вам необходимо сначала выделить память, прежде чем вы действительно сможете ее использовать.

0 голосов
/ 04 июля 2018

Вы переполняете буфер здесь:

e.a[0] = 2;

Это вызывает неопределенное поведение .

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

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

struct e1
{
    int a[1];
};
...