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)) ?

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

Как известно, со многими комитетскими бреднями разрабы не согласны компиляторов

Я предполагаю комитет во многом состоит из разрабов компиляторов. Вряд ли они сами с собой не согласны.

потому есть такое понятие как «стандарт де-факто» — и именно на него я тебе бы советовал ориентироваться, если ты хочешь писать работающие приложения, а не стандарты.

А при написании работающих приложений часто возникает необходимость кастить указатель на элемент к указателю на массив и делать другие бессмысленные вещи?

(Кстати, забавно, что в сишке «стандарты де-факто», без ключей, зарезающих оптимизации, иногда строже, чем стандарт.)

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

А как должна выглядеть «неублюдочная запись»?

int[4] arr;
int* a, b, c; // pointers to int
int(int arg1, int arg2) Proc;
X512 ★★★★★
()
Ответ на: комментарий от anonymous

Я предполагаю комитет во многом состоит из разрабов компиляторов. Вряд ли они сами с собой не согласны

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

А при написании работающих приложений часто возникает необходимость кастить указатель на элемент к указателю на массив и делать другие бессмысленные вещи?

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

Кстати, забавно, что в сишке «стандарты де-факто», без ключей, зарезающих оптимизации, иногда строже, чем стандарт

Ты пишешь про вполне конкретый GCC, который нынче доверху набит вахтерами. А вот для MSVC твои слова не актуальны.

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

let не нужен

Нужен, когда ты браузишь код в IDE или просто получает ошибку компиляции. Сишную дристню без четкого выраженного синтаксиса очень тяжело парсить даже при ошибке в одном символе. В случае крестов эта проблема еще больше усугубилось, в результате чего чисто синтаксический парсинг крестов невозможен, потому что нельзя отличить шаблонный тип от операторов сравнения и конструктор от объявления функции.

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

Я предполагаю комитет во многом состоит из разрабов компиляторов.

Нет.

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

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

шаблонный тип от операторов сравнения

Например?

конструктор от объявления функции

Опять же, пример? Конструктор как раз легко отличить по отсутствию типа результата.

anonymous
()

а почему

Потому что убогая сишечка. Возьми нормальный язык. C# или C++.

ox55ff ★★★★★
()

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

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

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

Тем не менее все крупные там представлены. Более того - имеет место быть право «implementers veto». Знаю пару конкретных случаев когда оно использовалось.

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

Потому что в си b и a НЕ трактуются как указатели, НЕ являются де-факто указателями и даже не могут быть преобразованы в них. То есть ты свою «божественную сишечку» не знаешь.

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

Потому что в си b и a НЕ трактуются как указатели

И именно поэтому там работает конструкция 0[a] ^_^.

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

Просвещайтесь!

#include <stdio.h>
int main() {
    int a[10];
    int *p;
    *(a+1)=123;
    p=a;
    *(p+2)=321;
    printf("Hello stuped! %d - %d\n",*(a+1), *(p+2));
    return 0;
}

что это сделает си хоть чуть ближе к питону

Про питон это фигура речи.

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

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

Все ведь просто!

Хотели КУШАТЬ и съели Кука ...
anonymous
()
Ответ на: комментарий от anonymous

И именно поэтому там работает конструкция 0[a] ^_^.

a[0] потому что может пониматься как указатель, но не a. Если думаешь, что а - указатель - попробуй присвоить ему новое значение

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

Это не дух языка, а смешивание семантики и реализации. Конструкции языка отображают семантику, их не следует путать с тем, как оно там реализуется на конкретном компьютере.

Можно представить себе процессор, где нет инструкции для деления (например) и «a / b» делается через вызов функции.

vlad9486
()
Ответ на: комментарий от byko3y
let a: [10]int;
let b: *[10]int = &a;

Лишь бы на Паскале не писать =)

var
  a:array[10] of integer;
  b:^array[10] of integer = @a;

Правда не помню, можно ли в FreePascal такое присваивание в объявлении сделать, если нет, то b = @a; придется в коде писать. Но все-равно как-то понятнее

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

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

Смотря какая WG. CWG вроде в основном из разработчиков компиляторов. (Правда, ХЗ кто там от MSVC.)

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

Можно представить себе процессор,

«Даёшь ассемблер!» Ну чо за баламуть? Не за процессоры речь!

anonymous
()
Ответ на: комментарий от Psilocybe
#include <stdio.h>

int main() {
    int a[10];
    int *p;
    a = p;
}

Готовы к такому просвещению?

$ gcc test.c
test.c: In function ‘main’:
test.c:6:7: error: assignment to expression with array type
    6 |     a = p;
      | 
Ой! Как же так вышло? Но ведь Psilocybe уверял, что массивы трактуются как указатели! Невероятно.. Как же теперь быть? :'-(

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

Я отвечал на сообщение, где

Однако, поскольку в Си замена языковых конструкций вызовами функции не свойственна

О каких еще вызовах функций здесь может идти речь?

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

О каких еще вызовах функций здесь может идти речь?

Да кто ж тебя поймёт, на какую пургу ты отвечал. Понятно лишь одно, не пришей к п@@@е рукав.

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

шаблонный тип от операторов сравнения

Например?

A<B>C;

конструктор от объявления функции

Опять же, пример? Конструктор как раз легко отличить по отсутствию типа результата

A B(C);

Вот еще примеры: https://wiki.sei.cmu.edu/confluence/display/cplusplus/DCL53-CPP. Do not write...

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

Severity: low
Likelyhood: unlikely

Это прямо первая хрень, об которую я ударился в крестах, мол «Invalid forward function declaration» — долго думал еще, при чем тут функция вообще, если я конструктор вызываю? Я же ссылку дал — там красивые примеры с фигурными и двойными круглыми скобками для устранения двусмысленности синтаксиса.

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

Смотря какая WG. CWG вроде в основном из разработчиков компиляторов. (Правда, ХЗ кто там от MSVC.)

Да, в CWG и LWG больше разработчиков компиляторов.

А так, Billy O’Neal говорит что примерно 10% комитета это разработчики компиляторов и стандартной библиотеки, а 90% просто представители крупных компаний, которые разрабатывают на С++.

https://imgur.com/a/Et2ROJF

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

классика кинематографа «сишечка - первая кровь», анонимов порвало в лоскуты )

пешите исчо )

olelookoe ★★★
()

Что тебе, ублюдку, не ясно в слове «семантика»? Тварина ты тупая, у тебя одна структура, с одним наполнением, но под разными именами (переменными).

Ты бы хоть проверил так ли это, прежде чем обкладывать всех:

#include <stdio.h>
int main()
{

  struct {int array[10]; } a, b;
  a.array[0]=1;
  b.array[0]=2;
  printf("a!=b:  a.array[0] = %d  b.array[0] = %d \n",a.array[0],b.array[0]);
  a=b;
  printf("after a = b:  a.array[0] = %d  b.array[0] = %d \n",a.array[0],b.array[0]);
  a.array[0]=3;
  printf("again a!=b:  a.array[0] = %d  b.array[0] = %d \n",a.array[0],b.array[0]);
return 0;
}

результат

$ gcc sttest.c
$ ./a.out
a!=b:  a.array[0] = 1  b.array[0] = 2 
after a = b:  a.array[0] = 2  b.array[0] = 2
again a!=b:  a.array[0] = 3  b.array[0] = 2

Как видно, a и b - совершенно разные, более того, при присваивании копируются по значению.

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

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

Страсти какие… Можно какие-нибудь примеры, что скрывается за этим утверждением?

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

Severity: low

Likelyhood: unlikely

Это прямо первая хрень, об которую я ударился в крестах

Ты как всякие любители плацебо с доказанным отсутствием эффекта. «Ну а вот мне помогло!». Ну помогло так помогло. На общую статистику это не влияет.

anonymous
()

int a[10]; как синтаксическая конструкция, это всегда было bss, как бы тут отдельные повара не усирались нам соврать.

Ох, какой кошмар. Ладно, следи за руками:

$ cat test.c
int main() {
    int x[10];
}
$ gcc -O0 -ggdb test.c
$ gdb ./a.out
(gdb) break 2
Breakpoint 1 at 0x1155: file test.c, line 3.
(gdb) run
Starting program: /tmp/a.out 

Breakpoint 1, main () at test.c:3
3	}
(gdb) info proc mappings
process 9062
Mapped address spaces:

          Start Addr           End Addr       Size     Offset objfile
      0x555555554000     0x555555555000     0x1000        0x0 /tmp/a.out
      0x555555555000     0x555555556000     0x1000     0x1000 /tmp/a.out
      0x555555556000     0x555555557000     0x1000     0x2000 /tmp/a.out
      0x555555557000     0x555555558000     0x1000     0x2000 /tmp/a.out
      0x555555558000     0x555555559000     0x1000     0x3000 /tmp/a.out
      0x7ffff7de1000     0x7ffff7de3000     0x2000        0x0 
      0x7ffff7de3000     0x7ffff7e05000    0x22000        0x0 /lib64/libc-2.33.so
      0x7ffff7e05000     0x7ffff7f49000   0x144000    0x22000 /lib64/libc-2.33.so
      0x7ffff7f49000     0x7ffff7f94000    0x4b000   0x166000 /lib64/libc-2.33.so
      0x7ffff7f94000     0x7ffff7f98000     0x4000   0x1b0000 /lib64/libc-2.33.so
      0x7ffff7f98000     0x7ffff7f9a000     0x2000   0x1b4000 /lib64/libc-2.33.so
      0x7ffff7f9a000     0x7ffff7fa0000     0x6000        0x0 
      0x7ffff7fc7000     0x7ffff7fcb000     0x4000        0x0 [vvar]
      0x7ffff7fcb000     0x7ffff7fcc000     0x1000        0x0 [vdso]
      0x7ffff7fcc000     0x7ffff7fcd000     0x1000        0x0 /lib64/ld-2.33.so
      0x7ffff7fcd000     0x7ffff7ff1000    0x24000     0x1000 /lib64/ld-2.33.so
      0x7ffff7ff1000     0x7ffff7ffb000     0xa000    0x25000 /lib64/ld-2.33.so
      0x7ffff7ffb000     0x7ffff7ffd000     0x2000    0x2e000 /lib64/ld-2.33.so
      0x7ffff7ffd000     0x7ffff7fff000     0x2000    0x30000 /lib64/ld-2.33.so
      0x7ffffffde000     0x7ffffffff000    0x21000        0x0 [stack]
  0xffffffffff600000 0xffffffffff601000     0x1000        0x0 [vsyscall]
(gdb) p &x
$1 = (int (*)[10]) 0x7fffffffddf0
(gdb) p &x[7]
$2 = (int *) 0x7fffffffde0c
(gdb) p &x[3]
$3 = (int *) 0x7fffffffddfc
(gdb) p &x[0]
$4 = (int *) 0x7fffffffddf0

Обращаем внимание на строку, где указаны адреса стека:

      0x7ffffffde000     0x7ffffffff000    0x21000        0x0 [stack]

И о ужас, массив как раз лежит в тех пределах, начиная с

(gdb) p &x[0]
$4 = (int *) 0x7fffffffddf0

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

Тут я, уже кого-то отправил учить значение слова «семантика». Давай и тебя туда же отправим.

Итак, теперь тебе надо довести пример до конца. То есть, как и твой коллега-долбоёб в конце сделать a = b. И потом объяснить на хуй ты именно так сделал.

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

при присваивании копируются по значению.

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

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

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

Хоть поржём.

И да. Тут кто-то обиженкой оказался. Блокируют по 5.3 или 5.2, не помню, да и похуй как-то. Делать тут явно нехуй.

anonymous
()

Сломалось ли бы что-то в языке

Да.

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

Не, вон истерика продолжается.

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

Для массива, который бы обосновался в bss, всё выглядело бы так:

int y[10];
int main() {
    int x[10];
}
(gdb) p &y[0]
$1 = (int *) 0x555555558060 <y>
(gdb) p &x[0]
$2 = (int *) 0x7fffffffddf0

Ты, берёшь, загружаешь код на исполнение, радостно обращаешься к неинициализированной переменной, пытаешься с нею что-то делать и ожидаешь что она во время твоего терибоньканья переменной будет оставаться в bss?!?

Занятно, что анон не видит разницы между значением переменной и адресом переменной. К неинициализированной переменной я не обращаюсь ;)

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

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

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

Итак, теперь тебе надо довести пример до конца. То есть, как и твой коллега-censored в конце сделать a = b. И потом объяснить на censored ты именно так сделал.

Значит так, это ведь твои слова:

Тварина ты тупая, у тебя одна структура, с одним наполнением, но под разными именами (переменными). Ну и на censored ты, дитя урода, присваиваешь а = b, если это и так одно и то же?

Я спецом жирным выделил. Ты считал, что в

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

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

То есть, как и твой коллега-censored в конце сделать a = b.

В коде выше Присвоение массивов в Си (комментарий) я как видишь присвоил a = b

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

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

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

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

Да хоть на петабайт на суперкомпе

Нет такого стека даже на суперкомпьютере.

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

А так, Billy O’Neal говорит что примерно 10% комитета это разработчики компиляторов и стандартной библиотеки, а 90% просто представители крупных компаний, которые разрабатывают на С++

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

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

Ой-вей и шо ты хочеш сказать своим никудышным примером? Что если указатель нельзя менять, то он перестает быть указателем?

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

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

своим никудышным примером?

Дай свой «пример». :)))

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

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

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

Или даже не надо ничего присваивать. Напиши программку,которая выведет и &a и просто a . Подумай как понимать то, что увидешь

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

Ой-вей и шо ты хочеш сказать своим никудышным примером? Что если указатель нельзя менять, то он перестает быть указателем?

Так можно договориться и до того, что структура является указателем :)

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

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