Неправильно ли выделять объединению достаточно памяти только для одного члена? - PullRequest
0 голосов
/ 22 декабря 2018

Можно ли выделить память, которой достаточно для размещения только определенного члена объединения?Я имею в виду что-то вроде этого:

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

union u;

union u{
    int a;
    long b[4096];
};

int main(){
    union u tmp = {.a = 42};
    union u *u = (union u*) malloc(sizeof(int)); //not malloc(sizeof(union u))
    memcpy(u, &tmp, sizeof(int));
    printf("u::a = %lu\n", u -> a);
}

sizeof(union u) равно sizeof(long[4096]), и было бы бесполезно тратить память на выделение 4096 * sizeof(long) для хранения одного int.

IsМожно ли сделать такую ​​вещь, как та, что выше?Или это неопределенное поведение?

Ответы [ 2 ]

0 голосов
/ 23 декабря 2018

Можно ли выделить память, которой достаточно для размещения только определенного члена объединения?

Да.Тем не менее, код не должен пытаться использовать элементы в нераспределенных частях.


Для ясности ниже используется union ab вместо union u.

Начальная часть кода: нетпроблемы.

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

union ab;

union ab {
    int a;
    long b[4096];
};

int main(){
    union ab tmp = {.a = 42};

Назначение указателя на ограниченную память не является проблемой для себя.Хотя для приведения типов нет необходимости, и я считаю, что распределение по размеру объекта / члена более информативно (легче кодировать, просматривать и поддерживать), чем распределение по размеру типа.

    // union ab *u = (union ab*) malloc(sizeof(int)); //not malloc(sizeof(union ab))
    union ab *u = malloc(sizeof u->a);

С копированием / назначением проблем нет, так как памяти, на которую указывает u, достаточно.

    memcpy(u, &tmp, sizeof(int));
    // or 
    u.a = tmp.a;

Печать - проблема, так как код использует несовпадающий спецификатор,В исправленном коде нет проблем при доступе к члену .a

    // printf("ab::a = %lu\n", u -> a);
    printf("ab::a = %d\n", u->a);

Пока проблем нет.

Некоторый новый код является проблемой, поскольку код пытается прочитать через u,вне выделенной памяти - это неопределенное поведение (UB).

    temp = *u;
}
0 голосов
/ 22 декабря 2018

Я нашел ответ, почему недопустимо использование объединения.N1570::6.2.5p(20):

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

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

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