Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 18.09.2011, 12:57   #1
mikebrownen
Пользователь
 
Регистрация: 18.09.2011
Сообщений: 21
По умолчанию Переворачивание массива на Си

Здравствуйте! Почему не работает эта функция? В ней я с помощью указателя переворачиваю массив.
Код:
void reverse(void *base, int nel, int width)
{
    void *bufer;
    int *i;
    for(i=*base;i<=*base+nel*width;i+=width)
    {
        *bufer=*base[i+(nel+1)*width];
        *base[i+(nel+1)*width]=*base[i];
        *base[i]=*bufer;
    }

}
mikebrownen вне форума Ответить с цитированием
Старый 18.09.2011, 13:23   #2
pproger
C++ hater
СтарожилДжуниор
 
Аватар для pproger
 
Регистрация: 19.07.2009
Сообщений: 3,333
По умолчанию

1. под буфер не выделил память
2. разыменовывать void указатель нельзя
I invented the term Object-Oriented, and I can tell you I did not have C++ in mind. (c)Alan Kay

My other car is cdr.

Q: Whats the object-oriented way to become wealthy?
A: Inheritance
pproger вне форума Ответить с цитированием
Старый 18.09.2011, 13:27   #3
mikebrownen
Пользователь
 
Регистрация: 18.09.2011
Сообщений: 21
По умолчанию

2.Я же просто меняю местами адреса в памяти а не беру значения...

1. Просто добавить mallock(width); ?

Последний раз редактировалось mikebrownen; 18.09.2011 в 13:31.
mikebrownen вне форума Ответить с цитированием
Старый 18.09.2011, 14:20   #4
pproger
C++ hater
СтарожилДжуниор
 
Аватар для pproger
 
Регистрация: 19.07.2009
Сообщений: 3,333
По умолчанию

2mikebrownen
Цитата:
*bufer=*base[i+(nel+1)*width];
ты РАЗЫМЕНОВЫВАЕШЬ указатель, который не инициализирован. к тому же void указатели нельзя так разыменовывать, как минимум, нужно привести к какому либо типу

Цитата:
1. Просто добавить mallock(width); ?
просто нужно подумать и написать правильно
I invented the term Object-Oriented, and I can tell you I did not have C++ in mind. (c)Alan Kay

My other car is cdr.

Q: Whats the object-oriented way to become wealthy?
A: Inheritance
pproger вне форума Ответить с цитированием
Старый 18.09.2011, 14:21   #5
Carbon
JAVA BEAN
Участник клуба
 
Аватар для Carbon
 
Регистрация: 22.04.2007
Сообщений: 1,329
По умолчанию

Арифметика над void указателями.

Итак, какого типа массив?

Хотя, пофиг, в принципе:
Код:
#include <stdio.h>
#include <malloc.h>
#include <string.h>

union _
{
	void * temp;
	char * result;
};

char * cast(void * ptr)
{
	union _ un;
	un.temp = ptr;
	return un.result;
}


void reverse(void * array, int count, int width)
{
	char * arrayMod = cast(array);
	void * buffer = malloc(width * sizeof(char));

	char * left = arrayMod;
	char * right = &arrayMod[(count - 1) * width];

	int i;
	for (i = 0; i < count / 2; ++i, left += width, right -= width)
	{
		memcpy(buffer, left, width * sizeof(char));
		memcpy(left, right, width * sizeof(char));
		memcpy(right, buffer, width * sizeof(char));
	}

	free(buffer);
}


int main(int argc, char ** argv)
{
	int array[] = { 12, 3, 0, -100, 7, 44, 5, 11 };
	reverse(array, sizeof(array) / sizeof(int), sizeof(int));

	int i;
	for (i = 0; i < sizeof(array) / sizeof(int); ++i)
		printf("%d ", array[i]);

	getchar();

	return 0;
}

Последний раз редактировалось Stilet; 18.09.2011 в 16:01.
Carbon вне форума Ответить с цитированием
Старый 18.09.2011, 17:56   #6
Сыроежка
Форумчанин
 
Регистрация: 01.07.2011
Сообщений: 423
По умолчанию

Цитата:
Сообщение от mikebrownen Посмотреть сообщение
Здравствуйте! Почему не работает эта функция? В ней я с помощью указателя переворачиваю массив.
Код:
void reverse(void *base, int nel, int width)
{
    void *bufer;
    int *i;
    for(i=*base;i<=*base+nel*width;i+=width)
    {
        *bufer=*base[i+(nel+1)*width];
        *base[i+(nel+1)*width]=*base[i];
        *base[i]=*bufer;
    }

}

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

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

Например, пусть задан указатель на int, который адресует массив целых чисел.

Код:
int a[3] = { 1, 2, 3 };

int *p = a;
Так как размер целого числа равен 4 на 32-битовых платформах, то вы думаете, что если к указателю p прибавить 4, то он будет указывать на второй элемент массива. На самом деле это не так! Выражение

Код:
p += 4;
на самом деле означает, что к адресу, хранимому в p, вы прибавялете 4 * sizeof( int), что равно 16! То есть если представить, что значение указателя равно 10000000, то операция P += 4 сделает указатель равным 10000010 (это в шестнадцатиричном виде), а не 10000004, как вы думаете.

Теперь снова возращаясь к типу указателя на void, то так как размер типа void неизвестен, то ваше выражение из цикла

Код:
i+=width
должно вычисляться как
Код:
i += width * sizeof( void )
Но так как размер типа void неизвестен, то компилятор должен выдать сообщение ошибке.
Из-за этого вашего непонимания проистекают и другие ошибки кода.
Со мной можно встретиться на www.clipper.borda.ru
Сыроежка вне форума Ответить с цитированием
Старый 18.09.2011, 18:44   #7
mikebrownen
Пользователь
 
Регистрация: 18.09.2011
Сообщений: 21
По умолчанию

ТО есть если мы не знаем тип массива то единственный вариант использовать чаровый указатель и побайтово переворачивать?
mikebrownen вне форума Ответить с цитированием
Старый 18.09.2011, 18:51   #8
Сыроежка
Форумчанин
 
Регистрация: 01.07.2011
Сообщений: 423
По умолчанию

Цитата:
Сообщение от mikebrownen Посмотреть сообщение
ТО есть если мы не знаем тип массива то единственный вариант использовать чаровый указатель и побайтово переворачивать?
Тип массиива всегда известен! Другое дело, что есть так называемые неполные типы, то есть тпы, о которых нет информации об их размере.

Например, у вас есть объявление какой-нибудь структуры

Код:
struct S;
Но ее определение дано где-нибудь ниже в коде. Тогда если вы объявите указатель на эту структуру

Код:
struct S *p;
То вы не можете инкрементировать указатель или прибавлять к нему целое число, так как размер структуры пока не известен. То есть в данном случае объявление структуры - это не полный тип.

Ежели вы хотите делать так, как вы себе представляете, то есть чтобы при прибавлении к указателю целого числа значение указателя менялось на это целое число, то вам надо преобразовать указатель в указатель на char, и, так как sizeof( char ) == 1, то вы сможете изменить значение указателя так, как вы себе это представляете.
Со мной можно встретиться на www.clipper.borda.ru
Сыроежка вне форума Ответить с цитированием
Старый 18.09.2011, 19:18   #9
Carbon
JAVA BEAN
Участник клуба
 
Аватар для Carbon
 
Регистрация: 22.04.2007
Сообщений: 1,329
По умолчанию

Цитата:
Сообщение от mikebrownen Посмотреть сообщение
ТО есть если мы не знаем тип массива то единственный вариант использовать чаровый указатель и побайтово переворачивать?
Где я тут побайтово переворачивал? Я поэлементно. Глянь, что я записываю в buffer. Даже если и так, тогда это было бы неправильно.

Цитата:
Сообщение от Сыроежка Посмотреть сообщение
Тип массиива всегда известен!
Забавно, а в функции он не известен. По крайней мере, так тс её описал. Типа функция для массивов любых типов, главное знать sizeof этого типа.
И да, в одном массиве вполне могут быть объекты разных типов, правда функция будет работать в том случае если у них у всех sizeof одинаковый.

Последний раз редактировалось Carbon; 18.09.2011 в 19:21.
Carbon вне форума Ответить с цитированием
Старый 22.09.2011, 20:59   #10
mikebrownen
Пользователь
 
Регистрация: 18.09.2011
Сообщений: 21
По умолчанию

Код:
#include <stdio.h>
#include <stdlib.h>
void reverse(void *base, int nel, int width)
{
    int i,j;
    char *left,*right,bufer;
    for(i=0;i<nel/2;i++)
        for(j=0;j<width;j++)
        {
            left=((char*)base+i*width+j);
            right=((char*)base+nel*width-(i+1)*width+j);
            bufer=*right;
            *right=*left;
            *left=bufer;
        }

}
int main()
{
    int i;
    char c[5]={'a','b','c','d','e'};
    reverse(c,sizeof(c)/sizeof(char),sizeof(char));
    for(i=0;i<5;i++)
    printf(" %s ",c[i]);
    return 0;
}
Почему здесь выход за границы массива? Вроде бы все в норме...
mikebrownen вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Произведение элементов массива в функции (передача массива в функцию) (Delphi) Toxa16 Помощь студентам 1 23.04.2011 04:42
Pascal: Составить программу генерирования массива B, состящего из отрицательных элементов массива a mrRastom Помощь студентам 2 15.01.2011 14:33
Сумма и произведение элементов массива, удовлетворяющих условию (генерация float массива) felodese Помощь студентам 1 11.11.2010 20:52
переворачивание массива denis2010 Помощь студентам 3 28.01.2010 09:17
переписать из массива в линейный двунаправленный список чётные элементы массива Black_Ak24 Помощь студентам 12 08.01.2008 00:44