LINUX.ORG.RU

Присвоение массивов в Си

 


0

1

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

То есть почему нельзя сделать так:

int a[10];
int b[10];
a = b;

Однако, если обернуть всё в структуру, то можно так:

struct {int array[10]; } a, b;
a = b;

Сломалось ли бы что-то в языке, если бы присвоение массивов a = b работало как условный memcpy(a, b, sizeof(b)) ?

★★★★★
Ответ на: комментарий от Waterlaz

Тебе даже компилятор словами «test.c:6:7: error: assignment to expression with array type» как бы намекает, что слева от «=» стоит массив, а не указатель.

Упротый поц. Массив это вся область памяти из 10 элементов в примере. Ид «a» это указатель на его начало, который, ессно менять нельзя.

У компилятора конечно же есть информация , что это не просто указатель, а указатель на начало массива и чтобы в этом убедиться достаточно сделать sizeof(a)

https://godbolt.org/z/53dobq7v9

Но в операциях адресной арифметики - это указатель. Вглядись теперь в свой тупой вопрос

То есть почему нельзя сделать так:

int a[10];
int b[10];
a = b;

Тут a и b учавствуют в выражении адресной арифметики как указатели. Вот поэтому так и нельзя сделать.

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

Вот поэтому так и нельзя сделать.

Что именно ты объяснил? Глаза протри. :)))

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

Упротый поц. Массив это вся область памяти из 10 элементов в примере. Ид «a» это указатель на его начало, который, ессно менять нельзя.

Когда закончились аргументы, но продолжать стоять на своём хочется, то единственный выход — оскорбления? :) Сколько тебе лет? 19? Я угадал? :)

У компилятора конечно же есть информация , что это не просто указатель, а указатель на начало массива и чтобы в этом убедиться достаточно сделать sizeof(a)

То есть ты хочешь сказать, что размер указателя на массив такой же, как и сам массив? :D Указатель на int[1000000] занимает 8МБ? :)

Но в операциях адресной арифметики - это указатель. Вглядись теперь в свой тупой вопрос

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

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

Можешь обратить внимание на стандарт: http://port70.net/~nsz/c/c11/n1570.html#6.7.6.2p8

8 EXAMPLE 2 Note the distinction between the declarations

extern int *x; extern int y[];

The first declares x to be a pointer to int; the second declares y to be an array of int of unspecified size (an incomplete type), the storage for which is defined elsewhere.

упс, стандарт считает, что это разные вещи.

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

Когда закончились аргументы, но продолжать стоять на своём хочется, то единственный выход — оскорбления? :) Сколько тебе лет? 19? Я угадал? :)

Не могу отказать себе в удовольствии называть вещи своими именами :)

То есть ты хочешь сказать, что размер указателя на массив такой же, как и сам массив? :D Указатель на int[1000000] занимает 8МБ? :)

Русский не родной чтоли? Трудности с пониманием?

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

Если нечто крякает как утка, выглядит как утка, то это утка. Но для тебя видимо нет.

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

упс, стандарт считает, что это разные вещи.

Сишечка появилась гораздо раньше, чем для нее написали стандарт старые пердуны из подкоммитетов.

extern int *x; extern int y[];

В чем для тебя разница на практике для этих случаев?

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

ШТАБЛЯДЬ?!?

Сука, бегом показывать где я предъявлял претензии к синтаксису? Бегом, сука!

Я тебе и твоему корефану-коньяку в гранит отлил за семантика, а не за синтаксис. А теперь, как этот клован говорит, «следи за руками». О чём я говорю и о чём ты пиздишь.

Итак. Вот эта вот хуерга struct {int array[10]; } a, b; и, далее, a = b ; говорит ровно об одном. Ты, точнее, не ты, а твой коллега-коньяк создал две одинаковых по смыслу структуры и, далее, начал гонять байтики через стек. Казалось бы, всё заебись. Компиль схавает и не подавится. Компиль и не такую хуйню схавать может, но правда, это не повод эту самую хуйню писать.

Так вот. У тебя при таком раскладе всё будет относительно заебись пока размер стека, который по дефолту для х86_64 составляет 8388608 байт или 8 мегабайт. Для, других архитектур значение может меняться, но нам предсказуемо похуй, т.к. мы так как ты стеком не пользуемся. Ну прогнал ты 10 байт, да и похуй.

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

  1. Нагрузишь машину какой-то хуйнёй, которую ты не удосужился обойти ибо туп как пробка. Скопируй в стек, скопируй из стека и так 2 гектара лопатить, ага.

  2. Если ты в пределах своего процесса рискнёшь сделать это один раз за время его жизни, то ты, сука, тем самым просто сожрёшь память, т.к., сюрприз-сюрприз, но сегмент стека не убывает. И, если твой код должен крутиться 24/7, то ты уебашил 2 гектара. Просто так. По своей тупости.

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

я как видишь присвоил a = b

Да, я уже вижу что вас тут мудаков толпа. Ещё тут где-то один клован бегал, у которого сегмент data в ПЗУ внезапно оказался…

Понимаешь в чём вся хуйня-то. Вот все вопли про небезопасность С можно отнести не к языку, который не ограничивает программиста в его долбоебизме. Опасность не в языке. Опасность, знаешь ли, в долбоёбах, которых к языку даже в строгом ошейнике и наморднике подпускать нельзя. Ведь, сука, если ты в прод так пишешь и ничего, блядь, дикого в этом в упор не видишь, упирая на то, что да похуй - компиль не подавился же, то тебя… В общем, придумай сам что с тобой надо сделать, у меня фантазия иссякла почти. Дальше я тебя уже всерьёз оскорблять буду.

Теперь, дятел ты новогодний, понял о чём я сразу разорался? Дошло почему? Или ты опять по обыкновению тупняк включить и будешь делать вид что всё ништяк и тут нет ни какой семантической проблемы?

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

У меня для тебя хуёвая весть. В проде за такое на первый раз срезают месячную премию, на второй увольняют с треском, пылью и копотью. Потому что тут, блядь, своими руками внесена проблема. И такого рода привычки к говнокоду, это изживается годами. Реально. И первый шаг - не думать сожрёт или не сожрёт компиль. Это уровень кодераста. Первый шаг это ответ на вопрос да нахуя ж ты так сделал. А вот это уже уровень программиста.

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

Массив это вся область памяти из 10 элементов в примере. Ид «a» это указатель на его начало, который, ессно менять нельзя.

+1! Лор, оказывается не до конца потерян.

Я ещё только добавлю что дрочить безумно переменные или другие типы данных из bss это крайне хуёвая идея. Просто потому, что это верная дорожка к UB. И тут программирование превращается волшебным образом в забавную игру под названием «свезёт аль нет». Может и не свезти. В особенности, если привыкли быть тупее компилятора. Тут тогда чего угодно ждать можно.

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

bss Шрёдингера какой-то. Переменная у нас находится в bss, пока мы её не потеребонькаем, но только тронь, как тут же на стеке оказывается :D

Прикинь, сынок, это ведь работа в начале загрузчика, а потом рантайма. Представь себе резервирование неинициализированной переменной на 8 гигов? Предлагаешь все 8 гигов сразу захерачить в data? Вот поэтому, когда при загрузке грузится в память elf, то в начале переменные в bss как были, так и есть минимальны и только потом, когда ты своими шаловливыми дрочильниками начинаешь их дёргать, только после этого они могут попасть в сегмент стека. Но когда они будут проинициализированы как положено и будут содержать какие-то данные, тогда они переедут в data.

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

Это не bss Шрёдингера, это просто ты долбоёб.

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

Не могу отказать себе в удовольствии называть вещи своими именами :)

Нет же. Ты же свою позицию не аргументируешь. Ты как пятилетний ребёнок просто кричишь «хочу чтобы было указателем!!!!». И когда в такой ситуации ты кого-то оскорбляешь, то чести тебе это не делает и лучше ты от этого не выглядишь.

Русский не родной чтоли? Трудности с пониманием?

Для меня — родной и потому я «что ли» пишу раздельно. Ты прочитай лучше, что такое sizeof. И почему это проблема, что для массива sizeof выдает не размер указателя.

Если нечто крякает как утка, выглядит как утка, то это утка. Но для тебя видимо нет.

Только оно не крякает:

int main(){
    int a[10];
    int *b;
    a = b;
}
Не плавает:
int main(){
    int a[10];
    a++;
}
И выглядит как массив:
#include <stdio.h>
int main(){
    int a[10];
    int *b;
    printf("%zu %zu\n", sizeof(a), sizeof(b));
}

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

Сишечка появилась гораздо раньше, чем для нее написали стандарт старые пердуны из подкоммитетов.

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

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

Я начинаю подозревать, что этот анон и есть псилоциб :3

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

пользователи компиляторов поддержали Си и создали C++.

Да, то что выше я говорил это про С++.

Вот выложили логи ноябрьского заседания комитета С: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2914.pdf

В комитете С нет представителей Microsoft. Они вроде и сами не хотят.

Интересно много ли там представителей GCC или LLVM…

А так почти все предложения которые они рассматривали они приняли. Если есть время можешь почитать обсуждения.

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

Я тебе и твоему корефану-коньяку в гранит отлил за семантика, а не за синтаксис. А теперь, как этот клован говорит, «следи за руками».

Я слово синтаксис не произносил. Короче, подзадолбал уже. Не знаю, ты или другой анонимус, но скорее ты судя по стилю, стал утверждать (сейчас в удаленных), что в struct {int array[10]; } a, b; - структура с одним наполнением, но разными переменными и присваивать бессмысленно, потому что одно и тоже. Я короткой программой показал, что НЕ одно и тоже. ВОТ И ВСЕ.

Про гигабайты и стек - это ты потом какого-то хрена стал утверждать, я гигабайты через локальные переменные копировать не собирался. Для гигабайтов есть куча. Просто заметил, что если очень хочется, то и такое возможно сработает где-то. И нефиг тут мне идиотизм приписывать. Я как раз и говорил, что программист должен понимать, что и зачем он делает.

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

Говнокода тут нет, пока речь о десятках байт или даже килобайт. Если гигабайты - надо по-любому хорошо подумать над тем, что пишешь. Если в продакшен пишется, если программа одноразовая часто проще не тратить лишнее время на оптимизации ради сиюминутного результата. Кстати, надо бы посмотреть код на асме, с чего ты взял, что копирование компилятор через push pop реализует, а не через mov* ?

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

Не думаю, что есть смысл что-то отвечать анону. Общаться с быдлом, которое хоть немного в теме — одно дело, а с чуваком, который то ли вообще ничего не понимает, то ли умело прикидывается, что ничего не понимает, — просто странно.

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

Не думаю, что есть смысл что-то отвечать анону.

Смысл очень даже есть, особенно когда сам деревянный в обе стороны. :)))

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

Кароч, ты отмазался. Сделал вид что ни хуя не понял про чё базар катаем. Ясно. Тебе с этим жить. Мне похуй. Реально. Я тебе показал на пальцах что такой стиль программирования это просто уебанство. Хватило одного взгляда. Потому что продемонстрированный подход влёгкую, в полпинка экстраполируется на более тяжёлые случаи. Когда не 10 байт, а дохулиард. И, если кодераст привык тупить, то он так и будет тупить что на 10 байтах, что на двух гигах.

Моя задача выполнена. А уж что ты извлечёшь или не извлечёшь из данного общения, это твои половые трудности.

Кстати, надо бы посмотреть код на асме, с чего ты взял, что копирование компилятор через push pop реализует, а не через mov* ?

Да почему ты считаешь что компиль обязан спасать тебя от последствий твоих же кривых рук?!? И кто тогда умнее - ты или компиль? И на хуй тогда ты нужен в качестве кожаного мешка между стулом и монитором?!?

Впрочем, ладно. Это уже риторический вопросы. С тобой закончил. Да, в принципе, и с общением в данной точке интернета вообще.

Удачи. Не косячь в коде.

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

Моя задача выполнена. А уж что ты извлечёшь или не извлечёшь из данного общения, это твои половые трудности.

Но ты же обосрался буквально по каждому вопросу =)

Впрочем, ладно. Это уже риторический вопросы. С тобой закончил. Да, в принципе, и с общением в данной точке интернета вообще.

Да ты уже третий раз обещаешь уйти :) Уверен, что и ещё раз прибежишь слюной брызгать.

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

Кисо обиделось? Да неужто?

Впрочем, кисо само начало понимать что здесь что-то не так… Видимо в твоём коде что-то совсем не так, конина ты дагестанская. Начало, говоришь, доходить?

А теперь я тебе ещё круче на яйца кислотой капну. Так и быть. Покажу куда ведёт дорожка с неуёмной дрочкой на bss.

Вот тебе уебанский код в твоём долбоёбо-стайл:

#include <stdio.h>

void func()
{
    char array[10];
    gets(array);
}

int main(int argc, char **argv)
{
    func();
}

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

Но тебе не понять. Я и не надеюсь. И да. Быдло здесь не я, матерящийся анон, а тихая и типа воспитанная мерзкая тварь как ты, которая за продукты своего типа интеллектуального труда, читай, за интеллектуальное говно, ещё и денег получает.

Точка. Надоело, извини.

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

Кисо обиделось? Да неужто?

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

Покажу куда ведёт дорожка с неуёмной дрочкой на bss.

What a story Mark, bss тут при чём? :D

Точка. Надоело, извини.

Но ты же опять вернёшься :D

Waterlaz ★★★★★
() автор топика

Сломалось ли бы что-то в языке, если бы присвоение массивов a = b работало как условный memcpy(a, b, sizeof(b)) ?

Да. Нужно тогда требовать чтобы a и b не пересекались, иначе для корректного копирования нужно чтобы memcpy работало в определённом направлении. Учитывая арифметику указателей получается куча гемора в компиляторе. И то, может ты как раз хочешь «некорректное» копирование, ситуация не однозначная.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

Да. Нужно тогда требовать чтобы a и b не пересекались

Хм. Как их заставить пересекаться без explicit casts? А с кастами я могу заставить пересекаться что угодно, вне зависимости от того массив это или нет.

bugfixer ★★★★★
()
Ответ на: комментарий от no-such-file

Да. Нужно тогда требовать чтобы a и b не пересекались, иначе для корректного копирования нужно чтобы memcpy работало в определённом направлении. Учитывая арифметику указателей получается куча гемора в компиляторе. И то, может ты как раз хочешь «некорректное» копирование, ситуация не однозначная.

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

Waterlaz ★★★★★
() автор топика
Ответ на: комментарий от no-such-file

Нужно тогда требовать чтобы a и b не пересекались, иначе для корректного копирования нужно чтобы memcpy работало в определённом направлении.

Как штатными средствами сишки сделать, чтобы такие массивы пересекались? Не могу сообразить. Мне на ум приходит только если извратиться как-то с extern и бинарным хаком

anonymous
()

Присвоение массивов в Си

Самый матершинный тред …

anonymous
()

Присвоение массивов в Си

Почему в треде ссылок нет?
Эти темы лет двадцать обговаривают 1567344 программиста.
Гуглим например «bss assembler», «bss С++», …
Полно ведь инфы …

anonymous
()
Ответ на: комментарий от no-such-file

Да. Нужно тогда требовать чтобы a и b не пересекались

Чукча не читатель, чукча требователь?

6.5.16.1 Simple assignment

3 If the value being stored in an object is read from another object that overlaps in any way the storage of the first object, then the overlap shall be exact and the two objects shall have qualified or unqualified versions of a compatible type; otherwise, the behavior is undefined.

anonymous
()

Присвоение массивов в Си

Разрабатываю API в котором в run-time на основании метаданных можно создавать объекты любой сложности и работать с ними …

И пока все ok! ...

О чем споры? …

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

Потому что bss не имеет отношения к теме. Кроме одного не самого здорового анона это никого не волнует, а он, очевидно, пруфы не способен выдать.

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

union

А «это» случаем не плюсы? ;)

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

Разрабатываю API в котором в run-time на основании метаданных можно создавать объекты любой сложности и работать с ними … И пока все ok! …

Шутка

Non problem потому, что компилятор в runt-time не используется.

Есть ГВОЗДИ /байты/ и   
есть МОЛОТОК /memcpy/! 

А больше ни чего то и не нужно! ...

Пудрят вам вот мозги «УЧЕНЫЕ МУЖИ» …
Не поддавайтесь …
С memory работа простая! …

Что касаемо абстракций, то они полезны для того, чтобы легче было оперировать ГВОЗДЯМИ! …

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

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

Для начала нужно сообразить, что массивов в сишечке нет. Есть сахарок для определения фиксированного буфера на стеке. И другой сахарок для косвенного доступа с индексацией. Второй используется в частности для «динамических массивов». Но в целом это два разных случая использования []. Одно с другим никак не связано. Поэтому

int a[10]; // буфер из 10 целых
int *b = a + 3;  // b[0] == a[3]

Если ты не согласен, тогда помимо «настоящих» массивов придётся выдумать синтаксис для декларации динамических массивов (типа крестового new), а также синтаксис для слайсов, чтобы как раз можно было декларировать пересекающиеся подмассивы. И никакой арифметики указателей. Ну и тогда уже можно думать про a=b с копированием.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

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

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

Но в целом это два разных случая использования []. Одно с другим никак не связано.

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

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

Так про массивы в любом языке можно сказать

Нет, не в любом. В других языках массивы являются самостоятельным типом данных, что в частности позволяет создавать динамические массивы указывая именно тип массива. Создай в сишечке массив через malloc чтобы он имел тип именно int[10], а потом приходи умничать.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Для начала нужно сообразить, что массивов в сишечке нет.

Вызывающе неверная информация.

Есть сахарок для определения фиксированного буфера на стеке.

Дважды бред.

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

union’ы абсолютно ничего не добавляют к случаю кастов: я точно также туда запихаю одинаковые структурки с префиксами разной длины, без массивов. Для пущей пикантности ещё и padding / alignment засапрешу. И будет то же самое.

bugfixer ★★★★★
()
Последнее исправление: bugfixer (всего исправлений: 1)
Ответ на: комментарий от no-such-file

Абаснуй

По большому счёту - зачем мне оно надо? С точки зрения семантики языка это много раз выше делали. Я не знаю что добавить. Asm читать в состоянии? Я мог бы скинуть пару образцово - показательных примеров, но опять же - зачем?

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

По большому счёту - зачем мне оно надо?

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

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

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

Ха. Например:

extern const char str1[];
extern const char* str2;

void func()
{
   printf("%s", str1);
   printf("%s", str2);
}

А теперь внимание - дизасемблируем и смотрим. Просвещаемся. Прозреваем ;)

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

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

Я как бе писал на Watcom C для DOS

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

Прозреваем

Я давно прозрел, что ты в шары долбишься. В одном случае метка используется для сохранения адреса (str2), а в другом метка сама является адресом (str1). И как бы что? Никакой разницы нет, т.к. в printf так и так передаётся адрес, а не массив целиком.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Никакой разницы нет

Вам уже показывали что sizeof() разный, я продемонстрировал что asm разный даже для тривиального случая. Да, конечно - одно и то же. Удачи!

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