Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > обьясните дураку :)


Автор: oleg1973 17.8.2003, 14:38

кароче использую компилер LCC-WIN32
почему когда делаю
unsigned long A;
A++; или А=А+1;
в результате А увеличивается на 4 ? а хотелось на 1 smile.gif

Автор: mr.DUDA 17.8.2003, 14:42
может, перепутал и сделал указатель
Код

     unsigned long *A;
     A++;     // A = A + sizeof(unsigned long)

?

Автор: oleg1973 17.8.2003, 14:53
опс да там unsigned long *A;
а почему на 4 увеличивается?smile.gif

Автор: RAN 17.8.2003, 15:03
Потому что C язык - умный. Можно считать, что операции '+', '-', '++', '--' перегружены для каждого типа. unsigned long* A - это указатель на длинное целое. Операция ++ увеличивает A на величину, равную кол-ву байт, занимаемых типом unsigned long, 4 байта.

Пример 1:
int arr[] = {1,2,3,4}
int *a = arr; //Сейчас a указывает на первый элемент массива (1)
a++; //В Win32 значение переменной a увеличится на 4, и она будет указывать на второй элемент (2)
a += 2; //Увеличится на 8 и укажет на четвёртый элемент.

Пример 2:
typedef struct {
int a1;
int a2;
} MyStruct; //Структура займёт 8 байт
MyStruct *st; //указатель на структуру

st++; //увеличит значение st на 8

Автор: mr.DUDA 17.8.2003, 16:54
ЗЫ, это всё чтобы легче с массивами работать было ч/з указатели, что-то подобное реализовано в STL (операторы ++ и -- любого итератора).
Код
int  *a = new int[10];   //  sizeof(int) = 4
a[3]     = 1;        // то-же самое что:
*(a+3) = 1;

// ...  и насчет того, что всё это даёт:
int  *b = a+2;    // теперь "b" указывает на 3-й элемент массива,
                         // а если бы (a+2) не было равно значению "a" плюс 8,
                         // то ничего подобного нельзя было бы сделать.

Автор: DENNN 18.8.2003, 10:29
Цитата
а почему на 4 увеличивается?

Потому что операция ++ для указателя означает переход к следующему в памяти элементу, а на твоем компилере unsigned long занимает 4 байта.

Автор: oleg1973 18.8.2003, 13:21
как все замороченоsmile.gif
а как сделать подобное ? тоесть указательна 1 увеличить
mov al,[esi]
inc esi
mov ah,[esi]

Автор: mr.DUDA 18.8.2003, 13:31
Преобразовываем наш указатель к "char *", увеличиваем на 1, преобразовываем обратно в unsigned long:
Код
unsigned long *A;
A = (unsigned long *)((char *)A + 1);

Автор: RAN 18.8.2003, 13:34
Цитата
а как сделать подобное ? тоесть указательна 1 увеличить

Три способа:
1. Преобразовать к указателю на тип, занимающий в памяти 1 байт (например, char* или byte*)
unsigned long *A;
( (char*)A )++;
Но если вдруг эти типы будут в будущем занимать больше одного байта в памяти, как это когда-то случилось с int, то ошибку найти будет сложно (забудешь - 100%)

2. Преобразовать к типу unsigned int.
( (unsigned)A )++;
Проблемы могут быть в том случае, если компилятор не сможет преобразовать. Вдруг когда-нибудь sizeof(void*) не будет равен sizeof(unsigned int). Что мало вероятно, но всё же... Однако это вызовет ошибку компилятора и не придётся ломать голову.

3. "Железный" способ: использовать, приведённый тобой код на asm'е.

P.S. Такое использование ++, как в первых двух примерах, возможно в Builder'е. MSVC не поддреживает. Но главное было передать смысл.

Автор: RAN 18.8.2003, 16:09
Чуть не забыл, на будущее:
Модератор: Пожалуйста, один топик - один вопрос.

Автор: DENNN 18.8.2003, 16:55
Цитата
акое использование ++, как в первых двух примерах, возможно в Builder'е. MSVC не поддреживает.

Это какое же "такое использование"?

Автор: oleg1973 18.8.2003, 17:04
smile.gif
кароче асм рулит smile.gif
а впрочем как всегда smile.gif

Автор: RAN 18.8.2003, 20:10
DENNN, введи ( (char*)A )++; в MSVC и он выдаст, что у оператора ++ должен быть lvalue.

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

Автор: oleg1973 19.8.2003, 12:54
RAN
просто понадбилось работать с 32 битным бэк буффером (4 байта на точку как извесно)
вот и все smile.gif
так как в си я не силен поэтому так и делал через указатель
может и другие способы есть я просто не знаю

Автор: mr.DUDA 19.8.2003, 13:07
oleg1973 что тебе мешает использовать указатель на такую структуру вместо "unsigned long*":
Код
union uRGB
{
     struct
     {
           char r;
           char g;
           char b;
           char a;
     } RGBA;
     unsigned long value;
 
     uRGB() {value = 0;}
};

// .... примерчик

void SomeFunc(void *back_buffer)
{
     uRGB  *pStruct = (uRGB *)back_buffer;
     for(int i=0; i<100; i++)
     {      
           pStruct->value = 0xff00ff00;   // можно работать с цветом "целиком"...
           pStruct->RGBA.r = 0xff;      // ...а можно работать с отдельными
           pStruct->RGBA.g = 0xa0;   // компонентами цвета каждой точки
           pStruct++;
     }
}

Автор: DENNN 19.8.2003, 13:16
Не надо велосипед изобретать. Если работа в буфере идет с числами unsigned long на кой спрашивается преобразовывать указатель к байтам?!
Почитайте, что вы тут понасоветовали, если человек язык только изучать начинает, то у него от таких советов крыша поедет.

Автор: Fantasist 19.8.2003, 19:29
Цитата
Такое использование ++, как в первых двух примерах, возможно в Builder'е. MSVC не поддреживает. Но главное было передать смысл



Тогда это глюк Билдера. Такое выражение не должно компилироваться.

Автор: oleg1973 19.8.2003, 20:34
ниче не мешает smile.gif
яж говорю я не спец в Си

Автор: mr.DUDA 19.8.2003, 22:14
ИМХО, легче и быстрее было бы работать с буфером через ASM (или я ошибаюсь ?).

Автор: oleg1973 19.8.2003, 23:16
совершенно верно smile.gif
просто так как я задался целью все таки выучить Си
вот и мучаюсь smile.gif
а на асме нет проблем

Автор: RAN 20.8.2003, 02:17
Fantasist, не согласен.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)