Гарантируется ли непрерывное выделение памяти для переменной в c?

#include<stdio.h>
int main()
{
    int a = 1, b = 10, c = 2;
    int *arr[] = {&a, &b, &c}; 
    printf("%d\n", *arr[arr[1]-arr[0]]);
    return 0;
}

Вот я получаю результат 10. Под выводом здесь я понимаю память для переменной a b c, выделенная непрерывно. Этот вывод статический или зависит от системы? Могу ли я ожидать такого же результата в другой системе? И гарантировано непрерывное выделение памяти для этих переменных? Здесь я использую компилятор gcc.

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

Eugene Sh. 18.03.2024 19:01

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

tadman 18.03.2024 19:06

Что вы подразумеваете под "this variable"?

gulpr 18.03.2024 19:35

Последовательность соседних элементов обычно называют «непрерывной», а не «непрерывной».

stark 18.03.2024 20:00
int arr[] = {1, 10, 2};int *a = &arr[0], *b = &arr[1], *c = &arr[2];printf("%d\n", arr[b - a]); может быть вариант
Ted Lyngmo 18.03.2024 20:58

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

Lundin 19.03.2024 08:45
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
154
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

arr[1]-arr[0] (то есть &b - &a) приводит к неопределенному поведению вашей программы (UB).
Вычитание двух указателей из разных массивов (или одного за его пределами) — это UB.

Когда вычитаются два указателя, оба должны указывать на элементы одного и того же объекта массива или на один, следующий за последним элементом объекта массива;
C2Xdr § 6.5.6 10


Гарантируется ли непрерывное выделение памяти для переменной в c?

Нет.

Этот вывод статический или зависит от системы?

Нет, это УБ. Иногда система может «работать» так, как хотелось бы, а иногда нет.

Могу ли я ожидать такого же результата в другой системе?

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

А непрерывное выделение памяти для этой переменной гарантировано?

Нет.

@AndrewHenle «Риск» UB в отношении arr[1]-arr[0] - это CYA. Если бы arr[0] == arr[1], arr[1]-arr[0] нормально. Конечно, если вернуться к &b - &a, то да, УБ.

chux - Reinstate Monica 18.03.2024 23:47

А непрерывное выделение памяти для этой переменной гарантировано?

Массивы.

Стандарт С: 6.2.5

Тип массива описывает непрерывно выделенный непустой набор объекты с определенным типом объекта-члена, называемым типом элемента.

И это означает, что тип объекта должен быть размещен в одном блоке памяти (поэтому байты из int не могут быть распределены по памяти - и переменная типа int будет храниться в непрерывном фрагменте памяти размером sizeof(int)).

Но порядок и место хранения разных переменных стандартом не указан, а только их время жизни (длительность хранения).

Гарантируется ли непрерывное выделение памяти для переменной в c?

Пространство для любого конкретного объекта является смежным. Сюда входят агрегатные объекты (структуры и массивы).

В противном случае пространство для коллекций отдельных объектов не гарантированно будет непрерывным, но это довольно сложно проверить, основываясь исключительно на функциях, определенных спецификацией языка. В частности, различия указателей, такие как ваш arr[1]-arr[0], определяются только для указателей на конец одного и того же массива или сразу за ним.

Под выводом здесь я понимаю память для переменной a b c, выделенная непрерывно.

Это правдоподобный вывод, но его нельзя поддержать только на основе спецификации языка.

Этот вывод статический или зависит от системы? Могу ли я ожидать такого же результата в другой системе?

В спецификации языка нет оснований полагать, что вы увидите то же самое в другой системе или даже последовательно в данной системе.

А непрерывное выделение памяти для этой переменной гарантировано?

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

УФ. опасно слишком много думать о памяти.

chux - Reinstate Monica 18.03.2024 23:56

Другие вопросы по теме