|
Перевод на Си
|
|||
---|---|---|---|
#18+
Как можно написать в Си? Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
... |
|||
:
Нравится:
Не нравится:
|
|||
08.09.2021, 15:47 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
Вообще-то это уже на Си... Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
08.09.2021, 15:48 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
R[j,0] - на 0 выражение должно иметь тип указателя на объект, но имеет тип "int" ... |
|||
:
Нравится:
Не нравится:
|
|||
08.09.2021, 15:51 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
Код: sql 1.
Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
08.09.2021, 15:53 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakov,ой, пардон, да R[j][0] = rp = 0; - вот здесь ... |
|||
:
Нравится:
Не нравится:
|
|||
08.09.2021, 15:56 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
ругается, что индексируемое значение не является ни массивом, ни указателем, ни вектором ... |
|||
:
Нравится:
Не нравится:
|
|||
08.09.2021, 15:58 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
kasper_, Покажи, как объявлено R. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.09.2021, 16:04 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
AmKad, Код: c 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
... |
|||
:
Нравится:
Не нравится:
|
|||
08.09.2021, 16:09 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
в с++ бы было Код: plaintext 1. 2.
... |
|||
:
Нравится:
Не нравится:
|
|||
08.09.2021, 16:11 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
Чтобы работать с двумерным массивом, надо знать размер "строки" массива. Если ты объявляешь int *R - то компилятор не знает насколько длинная строка в массиве и ругается. Так что тебе придется эмулировать двумерный массив вручную. Код: plaintext 1. 2. 3. 4.
... |
|||
:
Нравится:
Не нравится:
|
|||
08.09.2021, 16:20 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
На, поиграйся: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33.
... |
|||
:
Нравится:
Не нравится:
|
|||
08.09.2021, 16:39 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
kasper_, компилируешь С-код компилятором С++, он жестче проверяет типы. или компилируй как С или обнули указатель отдельно NULL Кстати, неверно объявлен R, должно быть int **R; ... |
|||
:
Нравится:
Не нравится:
|
|||
08.09.2021, 16:59 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
Siemargl компилируешь С-код компилятором С++, он жестче проверяет типы. Siemargl или компилируй как С или обнули указатель отдельно NULL Siemargl Кстати, неверно объявлен R, должно быть int **R; ... |
|||
:
Нравится:
Не нравится:
|
|||
08.09.2021, 17:15 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
Спасибо, буду разбираться ... |
|||
:
Нравится:
Не нравится:
|
|||
08.09.2021, 19:15 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
Что-то туплю. Сначала 1. У меня есть в буфере некая строка, её длину можно определить, как strlen(buf) 2. Мне нужно создать таблицу из двух строк, которая на С++ бы выглядела, как int R[2][strlen(buf)+1] 3. Пытаюсь реализовать это следующим образом: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
что-то не так? ... |
|||
:
Нравится:
Не нравится:
|
|||
08.09.2021, 20:16 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
Код: plaintext 1. 2. 3. 4.
... |
|||
:
Нравится:
Не нравится:
|
|||
08.09.2021, 20:41 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
White Owl Siemargl компилируешь С-код компилятором С++, он жестче проверяет типы. Siemargl или компилируй как С или обнули указатель отдельно NULL потому что у топика R[j][0] = rp = 0; в общем проблема из-за неверного типа R, но мой совет ниже неверен и обойти через int**R не получится (размер *R неизвестен и индексация будет неверной) White Owl Siemargl Кстати, неверно объявлен R, должно быть int **R; это да, я неправ, тут в С дырка - массив массивов немного не то, что массив указателей, хотя синтаксис один. собственно, прямого решения нет, только через пересчет индексов kasper_ Код: plaintext 1. 2. 3. 4.
... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 01:25 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
kasper_ что-то не так? **R не является R[][] даже близко. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 04:42 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
kasper_ 1. У меня есть в буфере некая строка, её длину можно определить, как strlen(buf) 2. Мне нужно создать таблицу из двух строк, которая на С++ бы выглядела, как int R[2][strlen(buf)+1] И будет у тебя int R[2][sizeof(buf)] а все строки не больше чем sizeof(buf)-1 и гарантия что (в данном месте) ты не порушишь память получив GPF. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 04:48 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
kasper_ Код: plaintext 1. 2. 3. 4.
Это массив указателей на массивы. Тут каждая строка "двумерного" массива может находится в любом месте памяти и для перехода с одной строки на другую надо обязательно обращаться к базовому массиву указателей. Так удобно делать если "строки" этого двумерного массива могут быть разной длины (естественно надо будет как-нибудь еще помнить длину "строк"), но для реальных ASCIIz строк такое действительно часто используется. Для целых и математики, все-же удобнее использовать массив массивов (int R[N][M] или int *R = malloc(N*M)) тогда "строки" двумерного массива строго одинаковой длины, все строки располагаются в памяти строго друг за другом и переход с одной строки на другую очень легко обрабатывается кешем процессора и намного быстрее работает. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 05:00 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
White Owl На, поиграйся: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 14:00 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
a guest White Owl На, поиграйся: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 15:12 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
White Owl a guest пропущено... UB. Ну и вообще я не знаю в стандарте C гарантий того, что (int*)arr это указатель на arr[0][0] (а в C++ явно гарантируется что это не так). ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 15:26 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
Если посмотреть на строку в другом контексте Код: plaintext 1. 2. 3.
то это будет равносильно Код: plaintext 1.
никакого UB тут нет и быть не может. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 15:38 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
a guestв C++ *явно* гарантируется что это не так В С++ явно гарантируется, что переменная типа "массив" неявно приводится к указателю на подлежащий тип, имеющий значение адреса первого (то бишь нулевого) элемента массива. От количества проделанных этих преобразований результат не меняется. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 15:45 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
Dima T Если посмотреть на строку в другом контексте Код: plaintext 1. 2. 3.
то это будет равносильно Код: plaintext 1.
никакого UB тут нет и быть не может. А по получается что-то вроде: - `float f; *(int*)&f = 0;` это UB! - если посмотреть в другом контексте — `int f; *(int*)&f = 0;` — то не UB (подразумевая, что значит и в первом случае не UB) ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 15:51 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakov a guestв C++ *явно* гарантируется что это не так В С++ явно гарантируется, что переменная типа "массив" неявно приводится к указателю на подлежащий тип, имеющий значение адреса первого (то бишь нулевого) элемента массива. От количества проделанных этих преобразований результат не меняется.Последнее предложение очень правильно. arr неявно приводтся к указателю на arr[0], последующее применение (int*) этого результата не меняет, (int*)arr это по-прежнему указатель на arr[0], а не arr[0][0]. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 15:54 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
a guestarr неявно приводтся к указателю на arr[0], последующее применение (int*) этого результата не меняет, (int*)arr это по-прежнему указатель на arr[0], а не arr[0][0]. Не совсем так. Сначала arr приводится к указателю на int[], потом этот массив приводится к *int, а потом явно преобразуется в *int (что есть no-op), и уже потом разыменовывается, получая чистую (законную) ссылку на нулевой элемент нулевого массива. Полная операция эквивалентна Код: sql 1. 2. 3.
Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 16:03 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakov a guestarr неявно приводтся к указателю на arr[0], последующее применение (int*) этого результата не меняет, (int*)arr это по-прежнему указатель на arr[0], а не arr[0][0]. Не совсем так. Сначала arr приводится к указателю на int[]Приводится к выражению типа int(*)[3] значение которого это «указатель на первый элемент arr» Dimitry Sibiryakov , потом этот массив приводится к *int ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 16:11 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
a guest White Owl пропущено... С чего это вдруг UB? Это как раз стандартная адресная арифметика. Ну и вообще я не знаю в стандарте C гарантий того, что (int*)arr это указатель на arr[0][0] (а в C++ явно гарантируется что это не так). Тут итерируется до N*M, потому что я знаю что там есть достаточно памяти для такой операции. Да, это опасная вещь и да, именно за такие трюки на С и катится большинство бочек. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 16:16 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
a guestПриводится к выражению типа int(*)[3] Нет, к массиву указателей оно не приводится. Квадратные скобки заменяются звёздочками справа налево: int[X][Y] -> int[X]* -> int*. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 16:22 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
a guest В другом контексте UB нет, но на то он и другой контекст. А у нас контекст не другой. А по получается что-то вроде: - `float f; *(int*)&f = 0;` это UB! - если посмотреть в другом контексте — `int f; *(int*)&f = 0;` — то не UB (подразумевая, что значит и в первом случае не UB) А вот тут ты не прав. Во втором примере ты просто берешь указатель на переменную, потом разименовываешь его получая на выходе ту же самую переменную. Так делать действительно можно и это не UB. А вот в первом, у тебя происходит смена типа для не взаимозаменяемых типов, причем как закодирован float в памяти зависит в первую очередь от железа, как там процессор хранит float (IEEE 754 это всего-лишь один из стандартов). То есть на разных процессорах, в разных компиляторах результат операции float f; *(int*)&f = 0; может быть разным, поэтому это действительно UB. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 16:26 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
White Owl a guest пропущено... «Стандартная адресная арифметика» это когда имея указатель на arr[0][0] (ведь ожидается что (int*)arr выдаст именно его?), итерируешь от 0 до M. А тут итерируется до N*M, что > M. Ну и вообще я не знаю в стандарте C гарантий того, что (int*)arr это указатель на arr[0][0] (а в C++ явно гарантируется что это не так). Про то, что такой каст выдаст указатель на первый элемент arr[0] — arr[0][0] — не сказано. White Owl Да, это опасная вещь и да, именно за такие трюки на С и катится большинство бочек. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 16:27 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakov a guestПриводится к выражению типа int(*)[3] Нет, к массиву указателей оно не приводится. Квадратные скобки заменяются звёздочками справа налево: int[X][Y] -> int[X]* -> int*. int(*)[3] это указатель на массив, массив указателей это int*[3]. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 16:28 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
a guest White Owl пропущено... Нет, arr выдаст указатель на arr[0][0]. Про то, что такой каст выдаст указатель на первый элемент arr[0] — arr[0][0] — не сказано. Мы делаем принудительное приведение типов. (int*)arr относится к имени arr, а не к его типу. Мы плюем на исходный тип. Как только мы начали делать каст - оно уже совершенно не важно какой там был тип изначально . У нас есть переменная и мы ей назначаем новый тип. Все. С тем же успехом можно сделать (char*)arr, (void*)arr, (struct CoolStruct*)arr - везде мы получим указатель на соответствующий тип численно равный &arr[0][0]. И да, результат такого каста можно кастовать обратно, если конечно ты знаешь куда. White Owl Ну или по консервативным оценкам — (int*)arr + i всегда UB, т.к. стандарт явно не разрешает такого обращения с кастованным указателем, а только разрешает кастить обратно. (int*)arr + i - эквивалентен (int*)(arr + i). То есть берем реальный тип arr (а это указатель на тип int[N][M]), прибавляем к нему sizeof(int[N][M])*i и полученный адрес принудительно приводим к указателю на int. Запись по такому адресу тебе почти гарантировано даст падение. Это тоже не UB, это адресная арифметика. А я в примере показывал ((int*)arr) + i - берем адрес, плюем на его оригинальный тип, приводим его к нужному типу, потом уже занимаемся арифметикой. И да, это опасная вещь если не понимаешь что делаешь или просто опечатался. Но опасная и неопределенная - это два разных прилагательных, не надо их путать :) ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 16:58 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
a guest int(*)[3] это указатель на массив ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 17:00 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
White Owl ... С тем же успехом можно сделать (char*)arr, (void*)arr, (struct CoolStruct*)arr - везде мы получим указатель на соответствующий тип численно равный &arr[0][0]. И да, результат такого каста можно кастовать обратно, если конечно ты знаешь куда. ... Не совсем, тут есть UB связанное с выравниванием типов, описано где то в стандарте. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 17:25 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
White OwlКак только мы начали делать каст - оно уже совершенно не важно какой там был тип изначально . Сишный каст С++ компиляторы преобразуют либо в static_cast, либо в reinterpret_cast по возможности. static_cast переменной массива в указатель не пройдёт: они несовместимы, поэтому массив сначала приводится к указателю и только потом идёт его reinterpret_cast. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 17:59 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
White Owl a guest int(*)[3] это указатель на массив ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 18:14 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
White Owl a guest пропущено... Стандарт с этим точно не согласен. Выражения с типом массив неявно преобразуются к указателю на первый элемент, а первый элемент у arr[2][3] это объект с типом arr[3]. А вот что значит каст от int(*)[3] к int* — ХЗ. Если читать стандарт, то он только говорит, что результат такого каста можно кастовать обратно и получить то же значение, что до первого каста (к int*). Про то, что такой каст выдаст указатель на первый элемент arr[0] — arr[0][0] — не сказано. Мы делаем принудительное приведение типов. (int*)arr относится к имени arr, а не к его типу. Мы плюем на исходный тип. Как только мы начали делать каст - оно уже совершенно не важно какой там был тип изначально . У нас есть переменная и мы ей назначаем новый тип. Все. White Owl С тем же успехом можно сделать (char*)arr, (void*)arr, (struct CoolStruct*)arr - везде мы получим указатель на соответствующий тип численно равный &arr[0][0]. White Owl Ну или по консервативным оценкам — (int*)arr + i всегда UB, т.к. стандарт явно не разрешает такого обращения с кастованным указателем, а только разрешает кастить обратно. (int*)arr + i - эквивалентен (int*)(arr + i).🤦♂️ White Owl То есть берем реальный тип arr (а это указатель на тип int[N][M]) White Owl И да, это опасная вещь если не понимаешь что делаешь или просто опечатался. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.09.2021, 20:04 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakov White OwlКак только мы начали делать каст - оно уже совершенно не важно какой там был тип изначально . Сишный каст С++ компиляторы преобразуют либо в static_cast, либо в reinterpret_cast по возможности. static_cast переменной массива в указатель не пройдёт: они несовместимы, поэтому массив сначала приводится к указателю и только потом идёт его reinterpret_cast. Вот ведь навертели гады! В принципе то оно понятно зачем и почему такие сложности. Но... с одной стороны, даже это не всегда помогает от самострела. А с другой, при попытке "все-же сделать каст, потому что я знаю что тут можно и нужно", начинаются иногда очень странные пляски с различными типами кастов и в итоге в ногу летит не пуля а целый заряд картечи. Мне, все же, более простой подход Си нравится больше. Он прост, примитивен, но надежен и полностью предсказуем. А вот вся эта палитра плюсовых кастов... Ух! Излишне усложнено и все равно не дает гарантию от ошибок. Лучше бы вообще запретили каст делать, больше пользы было бы. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.09.2021, 05:26 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
a guest ХЗ что такое "(int*)arr относится к имени arr". arr это lvalue Смена типа переменной имеет смысл (и делается) только на этапе компиляции, во время работы у программы есть только адреса памяти к которым обращаются команды типа mov. lvalue/rvalue здесь совершенно ни причем. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.09.2021, 05:33 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
White OwlВот ведь навертели гады! Из-за такой вот фигни в ГЦЦ 9 (вроде бы) перестал работать Сишный каст указателя на одну функцию к другой. В результате результат GetProcAddress() приходится прогонять через два явных каста. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
10.09.2021, 12:44 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
kasper_, Код: plaintext 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
11.09.2021, 21:52 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
Что выделение памяти не соответствует, то не моя забота... Пусть ТС додумывает. :) ... |
|||
:
Нравится:
Не нравится:
|
|||
11.09.2021, 22:32 |
|
Перевод на Си
|
|||
---|---|---|---|
#18+
White Owl a guest ХЗ что такое "(int*)arr относится к имени arr". arr это lvalue White Owl lvalue/rvalue здесь совершенно ни причем. White Owl a guest int(*)[3] это указатель на массив a guest White Owl И да, это опасная вещь если не понимаешь что делаешь или просто опечатался. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.09.2021, 20:08 |
|
|
start [/forum/topic.php?all=1&fid=57&tid=2017171]: |
0ms |
get settings: |
10ms |
get forum list: |
13ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
63ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
61ms |
get tp. blocked users: |
1ms |
others: | 267ms |
total: | 433ms |
0 / 0 |