powered by simpleCommunicator - 2.0.35     © 2025 Programmizd 02
Форумы / C++ [игнор отключен] [закрыт для гостей] / Перевод на Си
46 сообщений из 46, показаны все 2 страниц
Перевод на Си
    #40096027
kasper_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как можно написать в Си?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
for(j = 0; j <= 1; j++)
{
    R[j][0] = rp = 0;
    i = 1;
    while(i <= strlen(buf))
    {
        while(buf[i - rp - 1] == buf[i + j + rp])
            rp++;
        R[j][i] = rp;
        k = 1;
        while((R[j][i - k] != rp - k) && (k < rp))
        {
            R[j][i + k] = min(R[j][i - k],rp - k);
            k++;
        }
        rp = max(rp - k,0);
        i += k;
    }
}
...
Рейтинг: 0 / 0
Перевод на Си
    #40096028
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще-то это уже на Си...
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Перевод на Си
    #40096030
kasper_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
R[j,0] - на 0 выражение должно иметь тип указателя на объект, но имеет тип "int"
...
Рейтинг: 0 / 0
Перевод на Си
    #40096032
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
R[j][0]


Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Перевод на Си
    #40096036
kasper_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,ой, пардон, да R[j][0] = rp = 0; - вот здесь
...
Рейтинг: 0 / 0
Перевод на Си
    #40096038
kasper_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ругается, что индексируемое значение не является ни массивом, ни указателем, ни вектором
...
Рейтинг: 0 / 0
Перевод на Си
    #40096040
Фотография AmKad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kasper_,

Покажи, как объявлено R.
...
Рейтинг: 0 / 0
Перевод на Си
    #40096042
kasper_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AmKad,
Код: c
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
        int i, j, k,   // iterators
        rp;        // length of radius

        int *R;  // указатель на массив
        int n, m;
        n = 2;
        m = strlen(buf) + 1;
        // Выделение памяти
        R = (int*)malloc(n*m * sizeof(int));
        // Ввод элементов массива
        for (i = 0; i        {
            for (j = 0; j            {
                printf("R[%d][%d] = ", i, j);
                scanf("%d", (R + i*m + j));
            }
        }
...
Рейтинг: 0 / 0
Перевод на Си
    #40096044
kasper_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
в с++ бы было
Код: plaintext
1.
2.
    const int N = 20; //например
    int R[2][N+1];
...
Рейтинг: 0 / 0
Перевод на Си
    #40096047
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чтобы работать с двумерным массивом, надо знать размер "строки" массива.
Если ты объявляешь int *R - то компилятор не знает насколько длинная строка в массиве и ругается.
Так что тебе придется эмулировать двумерный массив вручную.

Код: plaintext
1.
2.
3.
4.
int *R = malloc( number_of_rows * row_size * sizeof(int));
R[ y*row_size + x ] = ...;
/// это полностью эквивалентно
* (R + y*row_size + x )  = ...;
...
Рейтинг: 0 / 0
Перевод на Си
    #40096059
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На, поиграйся:
Код: 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.
#include <stdio.h>

#define N 2
#define M 3
int main(int argc, char **argv) {
	int arr[N][M];

	printf("sizeof(arr) = %ld\n", sizeof(arr));
	printf("sizeof(arr[0]) = %ld\n\n", sizeof(arr[0]));

	for (int i=0; i<N*M; i++) {
		printf("%p = %d\n", ((int*)arr)+i, i);
		*(((int*)arr)+i) = i;
	}
	printf("\n");

	for(int n=0; n<N; n++) {
		for(int m=0; m<M; m++) {
			printf("%p ", &arr[n][m]);
		}
		printf("\n");
	}
	printf("\n");

	for(int n=0; n<N; n++) {
		for(int m=0; m<M; m++) {
			printf("%d ", arr[n][m]);
		}
		printf("\n");
	}

	return 0;
}
...
Рейтинг: 0 / 0
Перевод на Си
    #40096071
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kasper_,

компилируешь С-код компилятором С++, он жестче проверяет типы.

или компилируй как С или обнули указатель отдельно NULL

Кстати, неверно объявлен R, должно быть int **R;
...
Рейтинг: 0 / 0
Перевод на Си
    #40096081
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Siemargl
компилируешь С-код компилятором С++, он жестче проверяет типы.
Нет. Не жестче, а по другому.

Siemargl
или компилируй как С или обнули указатель отдельно NULL
Это зачем?

Siemargl
Кстати, неверно объявлен R, должно быть int **R;
Совсем не верный совет.
...
Рейтинг: 0 / 0
Перевод на Си
    #40096120
kasper_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо, буду разбираться
...
Рейтинг: 0 / 0
Перевод на Си
    #40096144
kasper_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что-то туплю. Сначала

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.
        int i, j, n, m;
        n = 2;
        m = strlen(buf) + 1;
        // Выделение памяти
        //R = (int*)malloc(n*m * sizeof(int));
        int **R = (int*)malloc(n*m * sizeof(int));
        // Ввод элементов массива
        for (i = 0; i<n; i++)
        {
            for (j = 0; j<m; j++)
            {
                printf("R[%d][%d] = ", i, j);
                scanf("%d", (R + i*m + j));
            }
        }



что-то не так?
...
Рейтинг: 0 / 0
Перевод на Си
    #40096152
kasper_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
int **R = (int **)malloc(n*sizeof(int *));
for(int i = 0; i < n; i++) {
    R[i] = (int *)malloc(m*sizeof(int));
}
...
Рейтинг: 0 / 0
Перевод на Си
    #40096182
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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.
int **R = (int **)malloc(n*sizeof(int *));
for(int i = 0; i < n; i++) {
    R[i] = (int *)malloc(m*sizeof(int));
}

Похоже на правду
...
Рейтинг: 0 / 0
Перевод на Си
    #40096187
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kasper_
что-то не так?
Двойной указатель "не так".
**R не является R[][] даже близко.
...
Рейтинг: 0 / 0
Перевод на Си
    #40096188
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kasper_
1. У меня есть в буфере некая строка, её длину можно определить, как strlen(buf)
2. Мне нужно создать таблицу из двух строк, которая на С++ бы выглядела, как int R[2][strlen(buf)+1]
Это очень не хороший и опасный подход. strlen() тебе выдаст фактическую длину строки, да. Но это одна строка, что если у тебя вторая строка будет длиннее первой? Лучше заранее ограничь длину строки, просто задай что "на вход мы получаем не больше стольки-то символов".
И будет у тебя int R[2][sizeof(buf)] а все строки не больше чем sizeof(buf)-1 и гарантия что (в данном месте) ты не порушишь память получив GPF.
...
Рейтинг: 0 / 0
Перевод на Си
    #40096190
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kasper_
Код: plaintext
1.
2.
3.
4.
int **R = (int **)malloc(n*sizeof(int *));
for(int i = 0; i < n; i++) {
    R[i] = (int *)malloc(m*sizeof(int));
}

Да, так можно. Но это уже другая структура данных.
Это массив указателей на массивы. Тут каждая строка "двумерного" массива может находится в любом месте памяти и для перехода с одной строки на другую надо обязательно обращаться к базовому массиву указателей.
Так удобно делать если "строки" этого двумерного массива могут быть разной длины (естественно надо будет как-нибудь еще помнить длину "строк"), но для реальных ASCIIz строк такое действительно часто используется.


Для целых и математики, все-же удобнее использовать массив массивов (int R[N][M] или int *R = malloc(N*M)) тогда "строки" двумерного массива строго одинаковой длины, все строки располагаются в памяти строго друг за другом и переход с одной строки на другую очень легко обрабатывается кешем процессора и намного быстрее работает.
...
Рейтинг: 0 / 0
Перевод на Си
    #40096331
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl
На, поиграйся:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
#include <stdio.h>

#define N 2
#define M 3
int main(int argc, char **argv) {
	int arr[N][M];

	printf("sizeof(arr) = %ld\n", sizeof(arr));
	printf("sizeof(arr[0]) = %ld\n\n", sizeof(arr[0]));

	for (int i=0; i<N*M; i++) {
		printf("%p = %d\n", ((int*)arr)+i, i);
		*(((int*)arr)+i) = i;
	}
        // ...
}

UB.
...
Рейтинг: 0 / 0
Перевод на Си
    #40096363
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guest
White Owl
На, поиграйся:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
#include <stdio.h>

#define N 2
#define M 3
int main(int argc, char **argv) {
	int arr[N][M];

	printf("sizeof(arr) = %ld\n", sizeof(arr));
	printf("sizeof(arr[0]) = %ld\n\n", sizeof(arr[0]));

	for (int i=0; i<N*M; i++) {
		printf("%p = %d\n", ((int*)arr)+i, i);
		*(((int*)arr)+i) = i;
	}
        // ...
}

UB.
С чего это вдруг UB? Это как раз стандартная адресная арифметика.
...
Рейтинг: 0 / 0
Перевод на Си
    #40096374
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl
a guest
пропущено...
UB.
С чего это вдруг UB? Это как раз стандартная адресная арифметика.
«Стандартная адресная арифметика» это когда имея указатель на arr[0][0] (ведь ожидается что (int*)arr выдаст именно его?), итерируешь от 0 до M. А тут итерируется до N*M, что > M.
Ну и вообще я не знаю в стандарте C гарантий того, что (int*)arr это указатель на arr[0][0] (а в C++ явно гарантируется что это не так).
...
Рейтинг: 0 / 0
Перевод на Си
    #40096382
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если посмотреть на строку в другом контексте
Код: plaintext
1.
2.
3.
int arr[N];
...
*(((int*)arr)+i) = i;


то это будет равносильно
Код: plaintext
1.
arr[i] = i;


никакого UB тут нет и быть не может.
...
Рейтинг: 0 / 0
Перевод на Си
    #40096386
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guestв C++ *явно* гарантируется что это не так

В С++ явно гарантируется, что переменная типа "массив" неявно приводится к
указателю на подлежащий тип, имеющий значение адреса первого (то бишь нулевого)
элемента массива. От количества проделанных этих преобразований результат не
меняется.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Перевод на Си
    #40096390
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima T
Если посмотреть на строку в другом контексте
Код: plaintext
1.
2.
3.
int arr[N];
...
*(((int*)arr)+i) = i;


то это будет равносильно
Код: plaintext
1.
arr[i] = i;


никакого UB тут нет и быть не может.
В другом контексте UB нет, но на то он и другой контекст. А у нас контекст не другой.
А по получается что-то вроде:
- `float f; *(int*)&f = 0;` это UB!
- если посмотреть в другом контексте — `int f; *(int*)&f = 0;` — то не UB (подразумевая, что значит и в первом случае не UB)
...
Рейтинг: 0 / 0
Перевод на Си
    #40096394
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakov

a guestв C++ *явно* гарантируется что это не так

В С++ явно гарантируется, что переменная типа "массив" неявно приводится к
указателю на подлежащий тип, имеющий значение адреса первого (то бишь нулевого)
элемента массива. От количества проделанных этих преобразований результат не
меняется.Последнее предложение очень правильно.
arr неявно приводтся к указателю на arr[0], последующее применение (int*) этого результата не меняет, (int*)arr это по-прежнему указатель на arr[0], а не arr[0][0].
...
Рейтинг: 0 / 0
Перевод на Си
    #40096402
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guestarr неявно приводтся к указателю на arr[0], последующее применение (int*) этого
результата не меняет, (int*)arr это по-прежнему указатель на arr[0], а не arr[0][0].

Не совсем так. Сначала arr приводится к указателю на int[], потом этот массив
приводится к *int, а потом явно преобразуется в *int (что есть no-op), и уже
потом разыменовывается, получая чистую (законную) ссылку на нулевой элемент
нулевого массива.

Полная операция эквивалентна
Код: sql
1.
2.
3.
int[M]* tmp = &arr[0];
int* tmp2 = &tmp[0];
*tmp2 + i = i;


Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Перевод на Си
    #40096406
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakov

a guestarr неявно приводтся к указателю на arr[0], последующее применение (int*) этого
результата не меняет, (int*)arr это по-прежнему указатель на arr[0], а не arr[0][0].

Не совсем так. Сначала arr приводится к указателю на int[]Приводится к выражению типа int(*)[3] значение которого это «указатель на первый элемент arr»
Dimitry Sibiryakov
, потом этот массив приводится к *int
Потом int(*)[3] никуда неявно не приводится, т.к. тип этого выражения уже не массив и каких-либо других неявных преобразований от int(*)[3] к int* не существует.
...
Рейтинг: 0 / 0
Перевод на Си
    #40096412
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guest
White Owl
пропущено...
С чего это вдруг UB? Это как раз стандартная адресная арифметика.
«Стандартная адресная арифметика» это когда имея указатель на arr[0][0] (ведь ожидается что (int*)arr выдаст именно его?), итерируешь от 0 до M. А тут итерируется до N*M, что > M.
Ну и вообще я не знаю в стандарте C гарантий того, что (int*)arr это указатель на arr[0][0] (а в C++ явно гарантируется что это не так).
Нет, arr выдаст указатель на arr[0][0]. А (int*)arr выдаст указатель на int который совпадает с адресом arr[0][0]. Это уже не массив а простой указатель.
Тут итерируется до N*M, потому что я знаю что там есть достаточно памяти для такой операции.
Да, это опасная вещь и да, именно за такие трюки на С и катится большинство бочек.
...
Рейтинг: 0 / 0
Перевод на Си
    #40096416
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guestПриводится к выражению типа int(*)[3]

Нет, к массиву указателей оно не приводится. Квадратные скобки заменяются
звёздочками справа налево:
int[X][Y] -> int[X]* -> int*.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Перевод на Си
    #40096419
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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.
...
Рейтинг: 0 / 0
Перевод на Си
    #40096420
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl
a guest
пропущено...
«Стандартная адресная арифметика» это когда имея указатель на arr[0][0] (ведь ожидается что (int*)arr выдаст именно его?), итерируешь от 0 до M. А тут итерируется до N*M, что > M.
Ну и вообще я не знаю в стандарте C гарантий того, что (int*)arr это указатель на arr[0][0] (а в C++ явно гарантируется что это не так).
Нет, arr выдаст указатель на arr[0][0].
Стандарт с этим точно не согласен. Выражения с типом массив неявно преобразуются к указателю на первый элемент, а первый элемент у arr[2][3] это объект с типом arr[3]. А вот что значит каст от int(*)[3] к int* — ХЗ. Если читать стандарт, то он только говорит, что результат такого каста можно кастовать обратно и получить то же значение, что до первого каста (к int*).
Про то, что такой каст выдаст указатель на первый элемент arr[0] — arr[0][0] — не сказано.

White Owl
Да, это опасная вещь и да, именно за такие трюки на С и катится большинство бочек.
Не знаю, что тут подразумевается под «опасной вещью». Либо поведение определено, либо не определено. И тут оно не определено. Как минимум из-за выхода за пределы массива arr[0], если верить что каст к int* выдаст указатель на первый элемент arr[0]. Ну или по консервативным оценкам — (int*)arr + i всегда UB, т.к. стандарт явно не разрешает такого обращения с кастованным указателем, а только разрешает кастить обратно.
...
Рейтинг: 0 / 0
Перевод на Си
    #40096423
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakov

a guestПриводится к выражению типа int(*)[3]

Нет, к массиву указателей оно не приводится. Квадратные скобки заменяются
звёздочками справа налево:
int[X][Y] -> int[X]* -> int*.
int(*)[3] это указатель на массив, массив указателей это int*[3].
...
Рейтинг: 0 / 0
Перевод на Си
    #40096446
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guest
White Owl
пропущено...
Нет, arr выдаст указатель на arr[0][0].
Стандарт с этим точно не согласен. Выражения с типом массив неявно преобразуются к указателю на первый элемент, а первый элемент у arr[2][3] это объект с типом arr[3]. А вот что значит каст от int(*)[3] к int* — ХЗ. Если читать стандарт, то он только говорит, что результат такого каста можно кастовать обратно и получить то же значение, что до первого каста (к int*).
Про то, что такой каст выдаст указатель на первый элемент arr[0] — arr[0][0] — не сказано.
Бррр... Зачем ты разбиваешь тип???
Мы делаем принудительное приведение типов. (int*)arr относится к имени arr, а не к его типу. Мы плюем на исходный тип. Как только мы начали делать каст - оно уже совершенно не важно какой там был тип изначально . У нас есть переменная и мы ей назначаем новый тип. Все.
С тем же успехом можно сделать (char*)arr, (void*)arr, (struct CoolStruct*)arr - везде мы получим указатель на соответствующий тип численно равный &arr[0][0].
И да, результат такого каста можно кастовать обратно, если конечно ты знаешь куда.

White Owl
Ну или по консервативным оценкам — (int*)arr + i всегда UB, т.к. стандарт явно не разрешает такого обращения с кастованным указателем, а только разрешает кастить обратно.
Неверно. Это как раз не UB а и есть стандарт адресной арифметики.
(int*)arr + i - эквивалентен (int*)(arr + i). То есть берем реальный тип arr (а это указатель на тип int[N][M]), прибавляем к нему sizeof(int[N][M])*i и полученный адрес принудительно приводим к указателю на int. Запись по такому адресу тебе почти гарантировано даст падение. Это тоже не UB, это адресная арифметика.
А я в примере показывал ((int*)arr) + i - берем адрес, плюем на его оригинальный тип, приводим его к нужному типу, потом уже занимаемся арифметикой.

И да, это опасная вещь если не понимаешь что делаешь или просто опечатался. Но опасная и неопределенная - это два разных прилагательных, не надо их путать :)
...
Рейтинг: 0 / 0
Перевод на Си
    #40096447
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guest
int(*)[3] это указатель на массив
Вообще-то, это не указатель на массив, а синтаксическая ошибка.
...
Рейтинг: 0 / 0
Перевод на Си
    #40096469
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White Owl
...
С тем же успехом можно сделать (char*)arr, (void*)arr, (struct CoolStruct*)arr - везде мы получим указатель на соответствующий тип численно равный &arr[0][0].
И да, результат такого каста можно кастовать обратно, если конечно ты знаешь куда.
...

Не совсем, тут есть UB связанное с выравниванием типов, описано где то в стандарте.
...
Рейтинг: 0 / 0
Перевод на Си
    #40096498
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White OwlКак только мы начали делать каст - оно уже совершенно не важно какой там был тип
изначально .

Сишный каст С++ компиляторы преобразуют либо в static_cast, либо в
reinterpret_cast по возможности. static_cast переменной массива в указатель не
пройдёт: они несовместимы, поэтому массив сначала приводится к указателю и
только потом идёт его reinterpret_cast.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Перевод на Си
    #40096507
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl
a guest
int(*)[3] это указатель на массив
Вообще-то, это не указатель на массив, а синтаксическая ошибка.
Если в файле написать только `int` и больше ничего, это тоже будет синтаксической ошибкой.
...
Рейтинг: 0 / 0
Перевод на Си
    #40096543
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl
a guest
пропущено...
Стандарт с этим точно не согласен. Выражения с типом массив неявно преобразуются к указателю на первый элемент, а первый элемент у arr[2][3] это объект с типом arr[3]. А вот что значит каст от int(*)[3] к int* — ХЗ. Если читать стандарт, то он только говорит, что результат такого каста можно кастовать обратно и получить то же значение, что до первого каста (к int*).
Про то, что такой каст выдаст указатель на первый элемент arr[0] — arr[0][0] — не сказано.
Бррр... Зачем ты разбиваешь тип???
Мы делаем принудительное приведение типов. (int*)arr относится к имени arr, а не к его типу. Мы плюем на исходный тип. Как только мы начали делать каст - оно уже совершенно не важно какой там был тип изначально . У нас есть переменная и мы ей назначаем новый тип. Все.
ХЗ что такое "(int*)arr относится к имени arr". arr это lvalue с типом int[2][3]. Когда такое выражение не является операндом sizeof, _Alignof или унарного &, то происходит преобразование массива к указателю. Получается выражение с типом int(*)[3] и значением "указатель на первый элемент соответствующего массива". Так что (int*) применяется к этому неявно преобразованному выражению, а не "имени переменной назначается новый тип".
White Owl
С тем же успехом можно сделать (char*)arr, (void*)arr, (struct CoolStruct*)arr - везде мы получим указатель на соответствующий тип численно равный &arr[0][0].
Ну, в отличие от кастов к другим типам, для каста к (char*) есть отдельное правило, это не просто смена типа выражения.

White Owl
Ну или по консервативным оценкам — (int*)arr + i всегда UB, т.к. стандарт явно не разрешает такого обращения с кастованным указателем, а только разрешает кастить обратно.
Неверно. Это как раз не UB а и есть стандарт адресной арифметики.
(int*)arr + i - эквивалентен (int*)(arr + i).🤦‍♂️
White Owl
То есть берем реальный тип arr (а это указатель на тип int[N][M])
Реальный тип arr это просто int[N][M].
White Owl
И да, это опасная вещь если не понимаешь что делаешь или просто опечатался.
"(int*)arr + i - эквивалентен (int*)(arr + i)" — это первое или второе?
...
Рейтинг: 0 / 0
Перевод на Си
    #40096590
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov

White OwlКак только мы начали делать каст - оно уже совершенно не важно какой там был тип
изначально .

Сишный каст С++ компиляторы преобразуют либо в static_cast, либо в
reinterpret_cast по возможности. static_cast переменной массива в указатель не
пройдёт: они несовместимы, поэтому массив сначала приводится к указателю и
только потом идёт его reinterpret_cast.
Вот ведь навертели гады!
В принципе то оно понятно зачем и почему такие сложности. Но... с одной стороны, даже это не всегда помогает от самострела. А с другой, при попытке "все-же сделать каст, потому что я знаю что тут можно и нужно", начинаются иногда очень странные пляски с различными типами кастов и в итоге в ногу летит не пуля а целый заряд картечи.
Мне, все же, более простой подход Си нравится больше. Он прост, примитивен, но надежен и полностью предсказуем. А вот вся эта палитра плюсовых кастов... Ух! Излишне усложнено и все равно не дает гарантию от ошибок. Лучше бы вообще запретили каст делать, больше пользы было бы.
...
Рейтинг: 0 / 0
Перевод на Си
    #40096592
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guest
ХЗ что такое "(int*)arr относится к имени arr". arr это lvalue
Нет. В рамках данной темы, arr это имя переменной. Это такая сущность имеющая значение только на этапе компилятора и линкера (ну еще остающаяся в дебаг сборке).
Смена типа переменной имеет смысл (и делается) только на этапе компиляции, во время работы у программы есть только адреса памяти к которым обращаются команды типа mov.
lvalue/rvalue здесь совершенно ни причем.
...
Рейтинг: 0 / 0
Перевод на Си
    #40096681
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White OwlВот ведь навертели гады!

Из-за такой вот фигни в ГЦЦ 9 (вроде бы) перестал работать Сишный каст указателя
на одну функцию к другой. В результате результат GetProcAddress() приходится
прогонять через два явных каста.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Перевод на Си
    #40096928
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kasper_,
Код: plaintext
1.
int* *R = reinterpret_cast<int**>( malloc(n*m * sizeof(int) ) );
...
Рейтинг: 0 / 0
Перевод на Си
    #40096930
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что выделение памяти не соответствует, то не моя забота... Пусть ТС додумывает. :)
...
Рейтинг: 0 / 0
Перевод на Си
    #40097659
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl
a guest
ХЗ что такое "(int*)arr относится к имени arr". arr это lvalue
Нет. В рамках данной темы, arr это имя переменной.
Которое, в выражениях, является lvalue. В рамках стандарта. Независимо от темы на SQL.ru.

White Owl
lvalue/rvalue здесь совершенно ни причем.
После такого или такого:
White Owl
a guest
int(*)[3] это указатель на массив
Вообще-то, это не указатель на массив, а синтаксическая ошибка.
и т.п. я всё больше склоняюсь к тому, что ответ на
a guest
White Owl
И да, это опасная вещь если не понимаешь что делаешь или просто опечатался.
"(int*)arr + i - эквивалентен (int*)(arr + i)" — это первое или второе?
это "первое".
...
Рейтинг: 0 / 0
46 сообщений из 46, показаны все 2 страниц
Форумы / C++ [игнор отключен] [закрыт для гостей] / Перевод на Си
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]