реклама на сайте
подробности

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> Компилятор Gcc или так и должнобыть?, Почему то отказывается выполнять инструкциии
Олег.
сообщение May 2 2008, 11:52
Сообщение #16


Участник
*

Группа: Участник
Сообщений: 19
Регистрация: 29-12-04
Пользователь №: 1 738



Да конечно так можно.. Я понимаю.. До меня дошло что к моменту взятия постинкремента тип к которому было приведение уже теряется и поэтому операция постинкремента уже не корректна. Интересно то что в Borlande приведение типа видимо сохраняется и далее постинкремент работает правильно в соответствии с приведённым типом.. Не буду спорить правильно ли это или нет но влюбом случае такой приём надо избегать.. я не собираюсь использовать это в коде проекта... smile.gif Просто столкнулся с разным поведением компиляторов при разборе синтаксиса пусть даже и не корректного..В любом случае благодарю за обсуждение. Спасибо.
Go to the top of the page
 
+Quote Post
777777
сообщение May 2 2008, 14:58
Сообщение #17


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(Олег. @ May 2 2008, 13:36) *
Не исключаю что косяк в моей голове..

А почему бы не сделать сразу этот указатель на unsigned long - и не придется ничего преобразовывать?
Цитата(Олег. @ May 2 2008, 13:36) *
Просто иногда очень удобено описать указатель на массив как void* и по ходу дела приводить и его к разным типам разыменовывая содержимое буферного массива чтобы не создавать кучу разных указателей на разные типы данных..

Ты пишешь на Си, а думаешь на ассемблере, и пытаешься помочь компилятору. Сделай над собой усилие и забудь об ассемблере - напиши программу, думая только об алгоритме. С твоей стороны помощь компилятору может заключаться в том, чтобы локализовать использование каждой переменной - объявлять ее только в той области видимости, где она используется, и минимизировать количество глобальных переменных.
Go to the top of the page
 
+Quote Post
Олег.
сообщение May 2 2008, 15:55
Сообщение #18


Участник
*

Группа: Участник
Сообщений: 19
Регистрация: 29-12-04
Пользователь №: 1 738



Да Вы в общем то правы. Да я пишу на С но всегда копаюсь в скомпилированом коде ассемблера. Как ни крути ну сильна привычка и любовь к железу.. пока не могу оторваться ибо до этого много работал на ассемблере. С приобретением опыта программирования на С думаю это пройдет но пока стараюсь и учусь. Спасибо.
Go to the top of the page
 
+Quote Post
777777
сообщение May 2 2008, 16:09
Сообщение #19


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(Олег. @ May 2 2008, 19:55) *
Да Вы в общем то правы. Да я пишу на С но всегда копаюсь в скомпилированом коде ассемблера.

Безусловно, в скомпилированном коде копаться нужно - все-таки не всегда код генерится достаточно эффективный, и когда компилятор создает что-то неудачное, программу надо менять. Но не таким варварским образом.
Go to the top of the page
 
+Quote Post
Andreas1
сообщение May 2 2008, 17:12
Сообщение #20


Местный
***

Группа: Свой
Сообщений: 446
Регистрация: 12-03-06
Из: Москва
Пользователь №: 15 142



поскольку только осваиваюсь в сях, а ситуация интересная, посоветовался с опытным человеком
Цитата
извините, но эта попытка инкрементировать временный объект....
*((T*) p)++
это на самом деле
T* tmp = (T*) p;
*tmp++
......Они все таки временные переменные сделали r-value...
а по старому стандарту это все законные выражения....

правильно это делается так
*(*(T**)&p)++

И действительно
b[0] = *(*(unsigned long int **)&ptr)++;
не вызвал ошибки и , судя по листингу, правильно инкрементировал ptr.
Правда пока не понял в чем разница 07.gif
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение May 2 2008, 17:35
Сообщение #21


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Andreas1 @ May 2 2008, 23:12) *
И действительно
b[0] = *(*(unsigned long int **)&ptr)++;
не вызвал ошибки и , судя по листингу, правильно инкрементировал ptr.
Правда пока не понял в чем разница 07.gif


Это то же, что предлагал ReAl немного выше. Разница в том, что в этом случае временный объект - указатель на наш указатель, и модифицируется не он (не временный объект), а то, на что он указывает (о как мощно задвинул:-) )
В принципе это тоже не комильфо, но работает.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
ReAl
сообщение May 2 2008, 19:15
Сообщение #22


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(Andreas1 @ May 2 2008, 20:12) *
поскольку только осваиваюсь в сях, а ситуация интересная, посоветовался с опытным человеком
Что значит "по старому стандарту"?
По K&R первого издания, являвшимся "стандартом де-факто", но не "де-юре"?
Я же привёл выше цитату из стандарта 1989 года про то, что cast не есть lvalue.

Другое дело, что многие компиляторы до конца 90-ых (а борлданд - так похоже и до середины 2010-ых :-) ) так и не удосужились привести себя в соответствие стандарту 1989 года, как и сейчас не все и не всё делают согласно стандарту 1999 года...

Цитата(AHTOXA @ May 2 2008, 20:35) *
Это то же, что предлагал ReAl немного выше.
Это то де по сути, но прозрачнее записано.
То, что написал я - можно подрихтовать, вставив вместо sizeof свой макрос, который как-то корректирует размер - например, в зависимости от параметра, задающего выравнивание.
У того же борланда, насколько я помню, так сделан макрос (а не __builtin) VA_ARG (stdarg.h).


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Alex03
сообщение May 5 2008, 12:01
Сообщение #23


Местный
***

Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034



А если так:

Код
unuon
{
    char *pc;
    int *pi;
    long *pl;
} u;

u.pc = &buff;

char c = *u.pc++;
int i = *u.pi++;
long l = *u.pl++;
Go to the top of the page
 
+Quote Post
777777
сообщение May 6 2008, 16:53
Сообщение #24


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(Alex03 @ May 5 2008, 16:01) *
А если так:

Код
unuon
{
    char *pc;
    int *pi;
    long *pl;
} u;

u.pc = &buff;

char c = *u.pc++;
int i = *u.pi++;
long l = *u.pl++;


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

Сообщение отредактировал 777777 - May 6 2008, 16:54
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение May 6 2008, 18:45
Сообщение #25


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(777777 @ May 6 2008, 22:53) *
Так можно. Только зачем? Языки высокого уровня придумываются для того, чтобы избегать низкоуровневых работ, а также для обнаружения большинства ошибок на этапе компиляции. А чего мы добиваемся подобной конструкцией?


Вы уже несколько раз это повторили. А нельзя ли привести пример того, как такое делается на языках высокого уровня? Скажем, вы принимаете сериализованный список переменных разного типа. То есть, принятый вами буфер выглядит следующим образом:
[число_переменных_в_пакете][номер_переменной1][переменная1][номер_переменной2][п
еременная2]...[номер_переменнойN][переменнаяN].
В зависимости от номера переменной её тип может быть int, char, double, long int.
Научите, как это делается на языках высокого уровня?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
777777
сообщение May 7 2008, 04:18
Сообщение #26


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(AHTOXA @ May 6 2008, 22:45) *
А нельзя ли привести пример того, как такое делается на языках высокого уровня? Скажем, вы принимаете сериализованный список переменных разного типа. То есть, принятый вами буфер выглядит следующим образом:
[число_переменных_в_пакете][номер_переменной1][переменная1][номер_переменной2][п
еременная2]...[номер_переменнойN][переменнаяN].
В зависимости от номера переменной её тип может быть int, char, double, long int.
Научите, как это делается на языках высокого уровня?


Очень просто. (Правда, номер переменной здесь не нужен - обычно порядок определяет назначение переменной). Можно написать функцию read(void* buf, uint8_t size) которая "принимает" (неважно откуда) данные размера size. Тогда мы пишем:

int var1;
char var2;
double var3;
long var4;
read(&var1, sizeof(var1));
read(&var2, sizeof(var2));
read(&var3, sizeof(var3));
read(&var4, sizeof(var4));

или еще проще:

struct VAR {
int var1;
char var2;
double var3;
long var4;
} var;
read(&var, sizeof(var));

Только здесь надо позаботиться чтобы переменные в стуктуре были выровнены побайтно. А самой функции read нет необходимости знать о типах - она читает только заданное количество байт.

Содержимое функции read зависит от того, откуда ей принимать данные, в любом случае ей придется инкрементировать указатель *buf. Если компилятор допускает ++ для типа void* и увеличивает его именно на 1, то такой код годится, если нет (как того требует стандарт) - то прототип функции должен быть read(char* buf, uint8_t size), но тогда при обращении к ней нужно приводить тип буфера к char*
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение May 7 2008, 04:54
Сообщение #27


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(777777 @ May 7 2008, 10:18) *
Очень просто. (Правда, номер переменной здесь не нужен - обычно порядок определяет назначение переменной).


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

Цитата
Можно написать функцию read(void* buf, uint8_t size) которая "принимает" (неважно откуда) данные размера size.


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

Цитата
Содержимое функции read зависит от того, откуда ей принимать данные, в любом случае ей придется инкрементировать указатель *buf. Если компилятор допускает ++ для типа void* и увеличивает его именно на 1, то такой код годится, если нет (как того требует стандарт) - то прототип функции должен быть read(char* buf, uint8_t size), но тогда при обращении к ней нужно приводить тип буфера к char*


Не вижу здесь никакого особого "высокоуровневого" подхода.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
777777
сообщение May 7 2008, 05:00
Сообщение #28


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(AHTOXA @ May 7 2008, 08:54) *
Собственно весь вопрос и заключался в том, как должна быть написана эта функция. Вы функцию не привели, и идеи ваши никуда не ушли в сторону от банальной арифметики с указателями.

Вы тоже не объяснили откуда плучаются данные.

void read(char* p, uint8_t n)
{
while(n--)
*p++ = getchar();
}

Каков вопрос, таков ответ smile.gif

А вообще, вопрос надо задавать более широко: что требуется в конечном итоге? Тогда, возможно, отпадет даже сама необходимость решать этот частный вопрос.

Сообщение отредактировал 777777 - May 7 2008, 05:02
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение May 7 2008, 05:03
Сообщение #29


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(777777 @ May 7 2008, 11:00) *
Вы тоже не объяснили откуда плучаются данные.


А какая разница?

Цитата
void read(char* p, uint8_t n)
{
while(n--)
*p++ = getchar();
}


Спасибо, теперь я наконец-таки узнал, как надо писать на языке высокого уровня biggrin.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 7 2008, 06:48
Сообщение #30


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(AHTOXA @ May 7 2008, 08:03) *
Спасибо, теперь я наконец-таки узнал, как надо писать на языке высокого уровня
Можно я чуток поправлю?
Любой указатель приводится к void* автоматически. В исходном коде компилятор не дал бы read(&var3, sizeof(var3)); только read((char *)&var3, sizeof(var3)):
Код
void read(void* pDst, uint8_t size)
{
    uint8_t *p = (uint8_t*)pDst;
    while(size--)
        *p++ = getchar();
}

Еще можно предположить, что размер переменной не может быть равным нулю. Тогда:
Код
void read(void* pDst, uint8_t size)
{
    uint8_t *p = (uint8_t*)pDst;
    do
        *p++ = getchar();
    while (--size);
}
Ну и отсюда всего один шаг до С++:
Код
template <typename T> void read(T & Dst)
{
    uint8_t *p = (uint8_t*)&Dst;
    do
        *p++ = getchar();
    while (--size);
}

read(var1);
read(var2);
read(var3);
Или, если экономим код, то
Код
void read(void* pDst, uint8_t size)
{
    uint8_t *p = (uint8_t*)pDst;
    do
        *p++ = getchar();
    while (--size);
}
template <typename T> void read(T & Dst)
{
    read(&T, sizeof(T));
}


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 14:02
Рейтинг@Mail.ru


Страница сгенерированна за 0.01483 секунд с 7
ELECTRONIX ©2004-2016