LINUX.ORG.RU

Си/Си++: отличие массивов от указателей

 , , ,


1

4

sizeof массива возвращает размер массива, sizeof указателя - лишь размер самого указателя. А ещё? В куче учебников есть оговорки, что в ряде других специфических ситуаций поведение компиляторов в отношении подобных переменных различается, но примеров навскидку найти не могу. В гугле был, в стандарте копаться лень.

★★★★★

массив это массив указатель это указатель непонятно что непонятно, тащто

В сишечке массивы как правило статические или стековые

lovesan ★☆ ()

В гугле был, в стандарте копаться лень.

А потом самолеты падают.

В Похожих симптоматичная тема от 2015 года.

Virtuos86 ★★★★★ ()
Последнее исправление: Virtuos86 (всего исправлений: 1)
Ответ на: комментарий от lovesan

https://imgur.com/a/GvQxg

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

meliafaro ★★★★★ ()
Ответ на: комментарий от Virtuos86

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

meliafaro ★★★★★ ()
Ответ на: комментарий от meliafaro

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

Здорово. А то, что не имея точного представления об этом, ты можешь нагородить багов, погроммируя, не является необходимостью?) Ох уж эти сишники…

Virtuos86 ★★★★★ ()
Ответ на: комментарий от meliafaro

Из чистого любобытства давно бы проверил

#include <stddef.h>

int main() {
    int ints[100];
    int *p;
    int i;

    ints = NULL;       // No
    ints = &i;         // No
    ints++;            // No                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                               
    p = NULL;          // Ok                                                                                                                                                                                                                                                   
    p = &i;            // Ok                                                                                                                                                                                                                                                   
    p++;               // Ok                                                                                                                                                                                                                                                   
}

fluorite ★★★★★ ()
Ответ на: комментарий от Virtuos86

https://imgur.com/a/GvQxg

И тебе кину. Багов нагородить в данном случае вряд ли, но всё же интересно. Так по существу будет что-то или ты чисто потроллить зашёл?

meliafaro ★★★★★ ()
Ответ на: комментарий от meliafaro

Походу человек не понял пресловутых стандартов, но написал книжку. Не читатель, короче.

Sorcerer ★★★★★ ()
Ответ на: комментарий от meliafaro

Мне не нравится допущения такого рода: «есть два исключения, но одно кривое, другое косое, поэтому мы их не рассматриваем». По-моему, разницу между массивами и указателями не придется сильно долго искать в стандарте, да и даже в любом толковом руководстве. Сам я такой информацией не обладаю, иначе бы уже написал.

Virtuos86 ★★★★★ ()
Ответ на: комментарий от fluorite

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

meliafaro ★★★★★ ()

Единственное исключение - это если ты объявишь массивом аргумент функции, но в данном случае это то же самое, что указатель.

anonymous ()
Ответ на: комментарий от meliafaro

объявленному единожды массиву нельзя присваивать произвольное значение

А объявленному дважды — можно!

utf8nowhere ★★ ()

В книге «Expert C programming» глава 4 посвящена этой теме.

t1nman ()

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

Пример из соседней ветки: error: invalid array assignment.

gag ★★★★★ ()

На реальном массиве не можно сделать realloc (очевидно).

KennyMinigun ★★★★★ ()

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

anonymous ()

Разница принципиальная.

Указатель - это область памяти (или регистр), которая содержит адрес ячейки памяти. Обращение к переменной (без операции разыменования) возвращает ее содержимое.

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

Таким образом переменная типа массив похожа на константный заранее инициализированный указатель.

German_1984 ★★ ()
Последнее исправление: German_1984 (всего исправлений: 2)
Ответ на: комментарий от German_1984

Таким образом массив похож на константный заранее инициализированный указатель.

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

vodz ★★★★★ ()
Ответ на: комментарий от meliafaro

Чушь, sizeof не единственное, и даже не самое важное отличие. Запихни массив в struct, и поймёшь.

unC0Rr ★★★★★ ()

Если ты массиву выделишь память посредством malloc и calloc то sizeof не покажет истиннового размера. Как я это помню.

u0atgKIRznY5 ()

Анонимус прав

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

А остальные пишут слабо относящиеся к вопросу вещи.

vlad9486 ()
Ответ на: комментарий от u0atgKIRznY5

Если выделять через malloc, то это не массив, а указатель на первый элемент массива, со всеми вытекающими

German_1984 ★★ ()
Ответ на: комментарий от meliafaro

Соглано C FAQ, три исключения — это оператор sizeof, оператор & и инициализация строковым литералом. Хотя операторы выравнивания тоже должны по-разному работать.

proud_anon ★★★★★ ()
Последнее исправление: proud_anon (всего исправлений: 1)

функция не может вернуть массив, а указатель может

xperious ()

Ещё про массивы

#include <iostream>                                                                  
                                                                                     
using namespace std;                                                                 
                                                                                     
int main()                                                                           
{                                                                                    
    int a[2] = {0, 1};                                                               
    cout << a << endl;                                                               
    cout << &a << endl;                                                              
                                                                                     
    cout << *a << endl;                                                              
    cout << *&a << endl;                                                             
    return 0;                                                                        
}

Вывод:

0x7ffedc3dbb50
0x7ffedc3dbb50
0
0x7ffedc3dbb50

Вопросы на подумать:

1. Почему a и &a выдали один и тот же адрес? Всегда ли так будет?

2. Почему в таком случае результат разыменования этих «одинаковых адресов» разный?

Для кого-то это конечно будет тривиально, но тем не менее..

Crocodoom ★★★ ()

Благодарю всех отписавшихся.

Подытожим: отличия - а) поведение оператора sizeof, б) поведение оператора & (вот это я упустил), в) поведение инициализации строковым литералом. В остальном, массив ничем не отличается от константного указателя, под который автоматически выделяется и освобождается память.

Я ничего не упустил, всё так?

meliafaro ★★★★★ ()
Ответ на: комментарий от meliafaro

В остальном, массив ничем не отличается от константного указателя

Я принципиально не хочу останавливаться на частных случаях, т. к. тут можно всегда что-то упустить. Запомни одно: под массивом в си подразумеваются 2 разных понятия — сам контейнер определённой длины (в т. ч. и нулевой длины, такие тоже разрешены) и константный указатель на 0-й элемент этого контейнера. Соответственно, в разных контекстах си-программы идентификатор массива может означать то одно, то другое. Но он всегда неперемещаем, поэтому адрес 0-ого элемента (как и других элементов) — всегда константа.

aureliano15 ()
Ответ на: комментарий от meliafaro

Массив можно передавать и принимать из функций по значению, если обернуть в struct.

unC0Rr ★★★★★ ()
Ответ на: комментарий от kirk_johnson

Но внутри стуктуры массив определённо ведёт себя отлично от указателя.

unC0Rr ★★★★★ ()
Ответ на: комментарий от unC0Rr

Он и вне структуры ведет себя отлично.

Массив — константный набор элементов с возможностью произвольного доступа по индексу. Все остальное — указатель на память с общим с массивом синтаксисом.

kirk_johnson ★☆ ()
Последнее исправление: kirk_johnson (всего исправлений: 1)
Ответ на: комментарий от meliafaro

Подытожим: отличия - б) поведение оператора &

Никаких принципиальных отличий в поведении оператора & для массивов и указателей нет. Оператор & для массива возвращает адрес массива, оператор & для указателя — адрес указателя.

Для переменных любого типа (неперегруженный) оператор & возвращает адрес объекта, обозначаемого именем переменной.

anonymous ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.