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

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


Участник
*

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



Столкнулся с тем что GCC упорно не хочет выполнять следующее, вроде с синтаксисом нет никакого криминала комерческие компиляторы отрабатывают без проблем (Borlad c++ и пр.) не выдавая никаких ошибок и предупреждений

unsigned long int a[] = {1, 2, 3, 4, 5};
unsigned long int b[5];

void* ptr = a;

b[0] = *((unsigned long int*)ptr)++;
b[1] = *((unsigned long long int*)ptr)++;

В обоих случаях отказывается делать инкремент указателя выдавая ошибку хотя здесь явно указатель приводится к указателю на заданный тип, пробовал указатель описать как указатель на тип char или int ситуация не меняется. С точки зрения синтаксиса вроде всё правильно .. пытался искать в стандарте Ansi C но нашел ничего .. Мож у кого есть какие мысли .. не исключаю что может и я что то делаю не коррекктно.. Конечно эту ситуацию можно обойти... Спасибо.
Go to the top of the page
 
+Quote Post
forever failure
сообщение May 2 2008, 04:43
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 256
Регистрация: 6-03-05
Из: Екатеринбург
Пользователь №: 3 112



Видимо имеется ввиду это:
warning: use of cast expressions as lvalues is deprecated
Означает, что операция преобразования типов не возвращает ссылку на объект, а следовательно не будет выполнятся его модификация.
Go to the top of the page
 
+Quote Post
777777
сообщение May 2 2008, 05:46
Сообщение #3


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

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



Цитата(Олег. @ May 2 2008, 08:17) *
Столкнулся с тем что GCC упорно не хочет выполнять следующее, вроде с синтаксисом нет никакого криминала комерческие компиляторы отрабатывают без проблем (Borlad c++ и пр.) не выдавая никаких ошибок и предупреждений

Борланд - худший из всех имеющихся в природе компиляторов, и ссылаться на него как на образец по меньшей мере смешно.
Цитата(Олег. @ May 2 2008, 08:17) *
unsigned long int a[] = {1, 2, 3, 4, 5};
unsigned long int b[5];

void* ptr = a;

b[0] = *((unsigned long int*)ptr)++;
b[1] = *((unsigned long long int*)ptr)++;

Ты пишешь на С, а думаешь по-ассемблерному. Не должно быть в С-программе такого количества преобразований типов. Не пытайся "помочь" компилятору подобным способом - этим ты ему только мешаешь. Просто пиши программу, думая лишь об алгоритме, а об оптимизации компилятор позаботится сам.
Go to the top of the page
 
+Quote Post
umup
сообщение May 2 2008, 06:48
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 226
Регистрация: 2-06-06
Пользователь №: 17 720



попробуйте так :

Код
  b[0] = *((unsigned long int *)ptr++);
  b[1] = *((unsigned long long int*)ptr++);
Go to the top of the page
 
+Quote Post
zltigo
сообщение May 2 2008, 07:13
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(777777 @ May 2 2008, 07:46) *
Борланд - худший из всех имеющихся в природе компиляторов...

smile.gif Не худший, но кривейший это точно - борлондячие продукты, что Cишные, что Паскалевские имеют свое "видение мира" и позволяют без труда писать всякую фигню, что, однако, позволило подсадить на них массу новичков считающих, что все так и должно быть sad.gif
Цитата(umup @ May 2 2008, 08:48) *
попробуйте так :

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

Цитата(Олег. @ May 2 2008, 06:17) *
комерческие компиляторы отрабатывают без проблем (Borlad c++ и пр.)

Про "и пр." это Вы для красного словца вверули.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ReAl
сообщение May 2 2008, 08:08
Сообщение #6


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

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



Цитата(Олег. @ May 2 2008, 07:17) *
вроде с синтаксисом нет никакого криминала комерческие компиляторы отрабатывают без проблем (Borlad c++ и пр.)

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

По поводу криминала - приведу выдержку из закона в подтверждение того, что выше уже было сказано:
Цитата
3.3.4 Cast operators
...
Preceding an expression by a parenthesized type name converts the
value of the expression to the named type. This construction is
called a cast. /36/
...
36. A cast does not yield an lvalue.
Причём это из стандарта С аж 89 года, в 99 это было подтверждено.
А раз кастированное выражение не lvalue - значит ему нельзя присвоить значение и ++ не проходит.

А обойти можно так:
Код
void* ptr;

char c;
short s;
int i;
long l;

#define GET_VALUE(p,t)  ( *(t*)( (*(char**)&p += sizeof(t)) - sizeof(t) ) )

void foo(void) {
    c = GET_VALUE( ptr, char);
    s = GET_VALUE( ptr, short);
    i = GET_VALUE( ptr, int);
    l = GET_VALUE( ptr, long);
}

При этом, правда, организуется доступ к объекту одного типа через приведение указателя на него к указателю на другой тип, что не всегда безопасно.
Будет предупреждение:
Цитата
warning: dereferencing type-punned pointer will break strict-aliasing rules


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


Местный
***

Группа: Свой
Сообщений: 226
Регистрация: 2-06-06
Пользователь №: 17 720



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

какая ?
компилируется нормально, без предупреждений.

то есть если нужно инкрементировать указатель, приведенный к другому типу :
Код
b[0] = *((unsigned long int *)ptr++);


а если содержимое этого указателя, то нужно добавить внешние скобки :
Код
b[0] = (*((unsigned long int *)ptr))++;


в обоих случаях нет никаких предупреждений.
Go to the top of the page
 
+Quote Post
ReAl
сообщение May 2 2008, 08:33
Сообщение #8


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

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



Цитата(umup @ May 2 2008, 09:48) *
попробуйте так :
Код
  b[0] = *((unsigned long int *)ptr++);
  b[1] = *((unsigned long long int*)ptr++);

А это абсолютно другой код. Согласно приоритетов ++ выполнится раньше приведения типа указателя.
А вот инкремент указателя на void - это, кажется, "неопределённое поведение".


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
zltigo
сообщение May 2 2008, 08:38
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(umup @ May 2 2008, 10:23) *
какая ?

Что-то типа, что c операциями с указателеми на void придется обломиться.
Цитата
компилируется нормально, без предупреждений.

Имя компилятора в студию smile.gif


Цитата(ReAl @ May 2 2008, 10:33) *
А вот инкремент указателя на void - это, кажется, "неопределённое поведение".

Без "кажется" - компилятор который молча инкрементирует указатель на неизвестный объект не может быть признан компилятором sad.gif


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
aesok
сообщение May 2 2008, 08:44
Сообщение #10


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(zltigo @ May 2 2008, 12:38) *
Без "кажется" - компилятор который молча инкрементирует указатель на неизвестный объект не может быть признан компилятором sad.gif


А если не молча, если про это в документации написано... smile.gif
Цитата
Arithmetic on void- and Function-Pointers
In GNU C, addition and subtraction operations are supported on pointers to void and on pointers to functions. This is done by treating the size of a void or of a function as 1.

A consequence of this is that sizeof is also allowed on void and on function types, and returns 1.

The option `-Wpointer-arith' requests a warning if these extensions are used.


Анатолий.

Сообщение отредактировал aesok - May 2 2008, 08:45
Go to the top of the page
 
+Quote Post
zltigo
сообщение May 2 2008, 08:48
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(aesok @ May 2 2008, 10:44) *
А если не молча, если про это в документации написано... smile.gif

Мрак. Хоть ключик под warning имеет место быть.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ReAl
сообщение May 2 2008, 09:02
Сообщение #12


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

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



Цитата(zltigo @ May 2 2008, 11:38) *
Имя компилятора в студию smile.gif
...
Без "кажется" - компилятор который молча инкрементирует указатель на неизвестный объект не может быть признан компилятором sad.gif
Ну, несколько я понимаю, "неопределённое поведение" означает, что компилятор может (имеет право) что-то сделать так или сяк, а молча ли он это сделает - зависит от включенного уровня предупреждений.
Учитывая

Сейчас проверил
Код
i = *((int*)ptr++);
gcc в данном месте независимо от размера объекта, к указателю на который делается приведение, увеличивает ptr на 1 (его право в случае UB), если есть ключ --pedantic, то выдаёт
Цитата
warning: wrong type argument to increment
Просто -Wall -Wextra для этого мало (для предупреждения на i = i++ их достаточно).

Цитата(aesok @ May 2 2008, 11:44) *
А если не молча, если про это в документации написано... smile.gif
...
Цитата
The option `-Wpointer-arith' requests a warning if these extensions are used.
Хм, я был уверен, что -Wall -Wextra включают все предпреждения...
Надо ещё раз перед сном перечитать документацию :-)


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Олег.
сообщение May 2 2008, 09:36
Сообщение #13


Участник
*

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



Я пробовал в Borland C++ Builder6, там всё проходит.. Конечно эту ситуацию можно обойти очень легко.. .Просто я вроде явно привожу указатель ок определённому типу информирую компилятор о том на объект какого типа он ссылается причём приведение типа срабатывает а вот инкремент нет.. причем дело тут не в void* можно указатель описать и как char* результат будет тот же. Не исключаю что косяк в моей голове.. Просто иногда очень удобено описать указатель на массив как void* и по ходу дела приводить и его к разным типам разыменовывая содержимое буферного массива чтобы не создавать кучу разных указателей на разные типы данных.. Опять же не утверждаю и не настаиваю что я прав я вполне могу ошибаться. smile.gif . Спасибо.
Go to the top of the page
 
+Quote Post
zltigo
сообщение May 2 2008, 09:41
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(ReAl @ May 2 2008, 11:02) *
gcc в данном месте независимо от размера объекта, к указателю на который делается приведение, увеличивает ptr на 1

Ну и разве это нормально?
Цитата
если есть ключ --pedantic, то выдаёт Просто -Wall -Wextra для этого мало..

Это плохо sad.gif. Действия с серьезными последствиями производятся и при этом даже warning на эти действия надо с дополнительными усилиями извлекать.
Попробовал
Код
b[0] = *((unsigned long int *)ptr++);

два моих самых используемых компилятора (IAR и Watcom ) выдали однозначную ошибку. Меня это очень порадовало - сам я такое не напишу - рука не поднимется, а вот чужого кода (очень разного качества sad.gif )достаточно много быват просматривать/править/использовать приходится и лишние проблемы совсем никчему.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
umup
сообщение May 2 2008, 10:30
Сообщение #15


Местный
***

Группа: Свой
Сообщений: 226
Регистрация: 2-06-06
Пользователь №: 17 720



можно так :
Код
b[0] = *(unsigned long *)ptr; ptr += sizeof(a[0]);
b[1] = *(unsigned long *)ptr; ptr += sizeof(a[0]);

или так :
Код
b[0] = ((unsigned long *)ptr)[0];
b[1] = ((unsigned long *)ptr)[1];
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 - 07:26
Рейтинг@Mail.ru


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