LINUX.ORG.RU

Тупняк и указатели 2

 


0

2

Я уже Вам надоел, да? Почти последний вопрос. Вопрос по «грамотности» указания элементов массива. Имеем

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define N 10
int main (){
	srand((unsigned)time(NULL));
	int **sq;
	sq=malloc(N*sizeof(int *));
	int i,j;
	for(i=0;i<N;i++){
	   //sq[i]=malloc(N*sizeof(int));
	   *(sq+i)=malloc(N*sizeof(int));
	   for(j=0;j<N;j++){
	       //sq[i][j]=rand();
	       *(*(sq+i)+j)=rand();
	   }
	}
	printf("%d\n",sq[5][5]);
	printf("%d\n",*(*(sq+5)+5));
	free(sq);
	return 0;
}
Как более внятно четко обращаться к элементу многомерного массива? sq[5][5] или *(*(sq+5)+5)? Да, и внесите Царя.

★★★★★

Последнее исправление: cetjs2 (всего исправлений: 2)

//простыня кода сонно проскипана

Тебе ж уже говорили в прошлом треде, что разницы по времени нет, а внятнее будет sq[5][5].

Deleted
()

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

kulti ★★
()

sq[5][5]

понятней

Но ты сначала объясни, на кой черт тебе многомерный массив? Одномерный дешевле!

Eddy_Em ☆☆☆☆☆
()

free(sq);

Ты правда считаешь, что этого будет достаточно?

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

Так в чем разница? Компилятор ведь ведь приводит многомерный к одномерному массиву, так?

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

Компилятор ведь ведь приводит многомерный к одномерному массиву, так?

В случаем массивов. У тебя в программе сишных массивов нет

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

Так в чем разница?

В количестве разыменований указателей.

Компилятор ведь ведь приводит многомерный к одномерному массиву, так?

Нет. Только если массив статический. А ты явно сделал двумерный (выделил массив указателей, потом каждый проинициализировал выделенным куском памяти). Т.е. тебе нужно сначала разыменовать нужный указатель для получения адреса начала N-й строки, затем разыменовать указатель по адресу M-го столбца.

Eddy_Em ☆☆☆☆☆
()

Второй вариант — только если ты хочешь попонтоваться перед одноклассниками. Да и то для таких целей лучше использовать следующую нотацию: 5[5[sq]].

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

Ну это даже не смешно

#define W 10
#define H 20

int *foo = malloc(W * H * sizeof(int));
int row, col;
for (row = 0; row < H; row++) {
  for (col = 0; col < W; col++) {
    foo[W * row + col] = 42;
  }
}
anonymous
()
Ответ на: комментарий от int13h

На N выделений памяти и возможно большую локальность.

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

ведь приводится авоматом, не?

int13h ★★★★★
() автор топика
Ответ на: комментарий от int13h
int (*foo)[N] = calloc(N*N, sizeof(int));
for(i=0; i<N; i++)
  for(j=0; j<N; j++)
    foo[i][j] = 42;
geks
()
Ответ на: комментарий от IvanR

Это нужно делать в С++, в С указатель на void может быть неявно приведён к любому другому указателю. Одна из наиболее явных несовместимостей С++ с С

Gvidon ★★★★
()

Тут есть маллок - таки пора вносить царя.

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

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

простите, забыл освободить память выделенную в цикле. Кстати, а существует ли реализация free(), которая освободила бы и память выделенную в цикле. Ведь если освобождается массив указателей, то, как мне кажется, можно было освободить и выделенную память на которую ссылаются эти указатели при вызове free(). Или я не прав?

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

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

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от int13h

Generic реализации нет, ибо void* нельзя разыменовывать.

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

Ведь если освобождается массив указателей, то, как мне кажется, можно было освободить и выделенную память на которую ссылаются эти указатели при вызове free(). Или я не прав?

А вдруг у тебя массив указателей на данные в стеке?

theNamelessOne ★★★★★
()

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

Если тебе надо именно многомерный массив, то надо делать так:

int *sq = malloc(W * H * sizeof(int));
и обращаться как тебе вздумается:
sq[5];
sq[row * W + col];
// или... внезапно...
int *sq3 = malloc(L * W * H * sizeof(int));
sq3[layer * L * W + row * W + col]; // получили трёхмерный массив размерами L x W x H
потому что «размерность массива - это вопрос индексации» (как кто-то сказал).

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

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

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

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

int arr[10];
Всякие маллоки и прочее возвращают указатели на какую-то память, которая может использоваться как угодно, в том числе и как массив.
Да, я зануда

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

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

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

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

$ cat ./test.c
#include <stdio.h>

#define H 2
#define W 3

int main ()
{
    int static_arr[H][W];
    int **dynamic_arr = malloc(H * sizeof(int*));
    *dynamic_arr = malloc(W * sizeof(int));
    int *tmp = malloc(10000 * sizeof(int));
    *(dynamic_arr+1) = malloc(W * sizeof(int));

    int N = 0;
    for(int r = 0; r < H; ++r)
        for(int c = 0; c < W; ++c)
        {
            static_arr[r][c] = N;
            dynamic_arr[r][c] = N++;
        }

    printf("static_arr[1][2]=%d, static_arr=%p, ptr=%p, idx=%ld\n",
            static_arr[1][2], static_arr, &static_arr[1][2],
            (long)&static_arr[1][2] - (long)static_arr);
    printf("dynamic_arr[1][2]=%d, dynamic_arr=%p, ptr=%p, idx=%ld\n",
            dynamic_arr[1][2], dynamic_arr, &dynamic_arr[1][2],
            (long)&dynamic_arr[1][2] - (long)dynamic_arr);

    free(*dynamic_arr);
    free(*(dynamic_arr+1));
    free(dynamic_arr);
    free(tmp);

    return 0;
}

$ gcc -std=c99 ./test.c
$ ./a.out
static_arr[1][2]=5, static_arr=0xbf95b564, ptr=0xbf95b578, idx=20
dynamic_arr[1][2]=5, dynamic_arr=0x83bf008, ptr=0x83c8c78, idx=40048
$

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

Советую тебе вообще на освобождение памяти внимания не обращать ибо ты никогда не напишешь программу, которой это будет необходимо. За тебя все ОС сделает когда твой 3х строчный маин закончится.

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

Советую тебе вообще на освобождение памяти внимания не обращать

Убивать!

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

какой ты толстячок

твой код, в котором надо освобождать память или трепло

я жду тут 2 года, пока ЛОР ставит на тебя клеймо, вывесишь код - снимется

жги, лалка!

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

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

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

Вопрос по «грамотности» указания элементов массива. Имеем

Ещё раз - у тебя не массив. Массив в сишке - это int m[10];

Никаких двумерных массивов в сишке нет, и если ты юзаешь так: sq[5][5] или *(*(sq+5)+5)? - ты ничтожество.

Скобочки юзаются, когда у тебя осмысленные индексы.

typedef enum {TYPE_A, TYPE_B, TYPE_C} type_t;

void type_a(void) {
  fprintf(stderr, "%s()\n", __FUNCTION__);
}
void type_b(void) {
  fprintf(stderr, "%s()\n", __FUNCTION__);
}
void type_c(void) {
  fprintf(stderr, "%s()\n", __FUNCTION__);
}

void (*m[])(void) = {type_a, type_b, type_c};

int main(void) {
  m[TYPE_A]();
  m[TYPE_B]();
  m[TYPE_C]();
  type_t type = TYPE_B;
  m[type]();
}

Тоже самое, если у тебя:

m[type][sub_type]();

Когда же у тебя индекс не осмысленный, да и вообще не является индексом, а обосанный анскильный счётчик - ты даун.

Как это делается - я уже писал в прошлой теме:

int main(void) {
  srand(time(NULL));
  buf_t buf = buf_malloc(int[10], 10);

  buf_foreach(int, it, buf) it = rand();

  buf_foreach(int, it, buf) fprintf(stderr, "%i ", it);fprintf(stderr, "\n");

  fprintf(stderr, "%i\n", *((int *)buf_begin(buf) + 10 * 1 + 0));//это не нужно в 99случев, если тебе нужно - храни длинну строки. 10*sizeof(int) в данном случае.
  buf_free(buf);
}

Бесполезный доступ по строкалайне, аля [5][5] - нахрен не нужен почти никогда, а когда нужен - это делается по другому.

Максимум на что делят - это на строки, для этого хранят тупо длину строки.

*(sq+i)=malloc(N*sizeof(int));//Это просто ублюдство, так делают только тотально больные на головку.
anonymous
()
Ответ на: комментарий от int13h

какой ты толстячок

Но анон прав же. Для короткоживущих программ в этом нет никакой необходимости.

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

надо различать статический двумерный массив и массив указателей на одномерные массивы

Слово «статический» тут не причем. Двумерная бывает индексация, а не массив.

И да, не пиши на этом языке, пж - для тебя есть пхп.

(long)dynamic_arr
-std=c99

Ну ты понял.

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

Што это за убожество? В каком пту учат писать так? А главное - зачем?

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

Ну ты и бред несешь! Скажем, считаю я БПФ и прочую хрень. Понавыделял 2ГБ оперативы, потом еще 2ГБ... И неиспользуемое не освобождать? Ну-ну...

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

Понавыделял 2ГБ оперативы, потом еще 2ГБ...

Зачем ещё раз 2Гб? Используй что есть повторно. Нафига тебе отдавать память и тут же брать её обратно?

no-such-file ★★★★★
()

1. у тебя протекла память.

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

Лень мне всю подноготную читать, но сдается мне, что уменьшение объема выделенной памяти realloc'ом будет медленнее. Ну, пофиг. Не использую — и всē!

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от mix_mix

А я вообще не программист. Нефиг тут!

Я разрабатываю электронику и пишу программульки только для решения всяких разных задач, а не ради разработки (хотя, не скрываю, что процесс нравится).

Eddy_Em ☆☆☆☆☆
()

какая шавка тут накрысятничала? верни дискуссию, уважаемый

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