The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  вход/выход  слежка  RSS
"Варнинг при -std=gnu99. Помогите разбраться."
Вариант для распечатки  
Пред. тема | След. тема 
Форум Программирование под UNIX (C/C++)
Изначальное сообщение [ Отслеживать ]

"Варнинг при -std=gnu99. Помогите разбраться."  +/
Сообщение от Nah email on 28-Фев-11, 15:15 
Здрасти, всем.

Решил собирать проект с опцией -std=gnu99.
Все хорошо, но есть один warning и я не понимаю его смысл.

---<Код proba.c>----------------------------------------
#include <stdio.h>
typedef unsigned char TMac[6];
void f(const TMac* mac)
{
    puts(mac?"mac":"no mac");
}  
int main()
{
    /*const*/ TMac mac;
    f(&mac);
    return 0;
}
---</Код proba.c>----------------------------------------

gcc -std=gnu99 -o q proba.c
proba.c: In function ‘main’:
proba.c:10: warning: passing argument 1 of ‘f’ from incompatible pointer type
proba.c:3: note: expected ‘const unsigned char (*)[6]’ but argument is of type ‘unsigned char (*)[6]’

Соответственно, если раскоментировать /*const*/ то варнинга не будет.

Так что же не нравится копилятору и как написать коректно?

Например, если функция ждет аргумент "const int*", а передается "int*", то все ОК и внутри функции аргумент будет указателем на константный инт.
Вроде, у меня ситуация аналогична.

Ещё раз, что же не нравится копилятору и как написать коректно?

Ответить | Правка | Cообщить модератору

Оглавление

Сообщения по теме [Сортировка по времени | RSS]


1. "Варнинг при -std=gnu99. Помогите разбраться."  +/
Сообщение от const86 (ok) on 28-Фев-11, 18:18 
Заверни массив в структуру - проще жизнь станет.
Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

2. "Варнинг при -std=gnu99. Помогите разбраться."  +/
Сообщение от Nah email on 01-Мрт-11, 06:18 
> Заверни массив в структуру - проще жизнь станет.

Не вариант - это уже устоявшаяся конструкция (проект большой, работают несколько человек).
К тому же, интересно разобраться, как с точки зрения компилятора написать корректно в этом случае.

Ответить | Правка | ^ к родителю #1 | Наверх | Cообщить модератору

3. "Варнинг при -std=gnu99. Помогите разбраться."  +/
Сообщение от diff (??) on 01-Мрт-11, 10:04 
>[оверквотинг удален]
> void f(const TMac* mac)
> {
>     puts(mac?"mac":"no mac");
> }
> int main()
> {
>     /*const*/ TMac mac;
>     f(&mac);
>     return 0;
> }

Для С подойдет приведение типов при вызове:
f((const TMac *)&mac);

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

4. "Варнинг при -std=gnu99. Помогите разбраться."  +/
Сообщение от Nah email on 01-Мрт-11, 10:34 
> Для С подойдет приведение типов при вызове:
> f((const TMac *)&mac);

Да, тогда варнинга не будет. Еще можно убрать const в функции. Да и на варнинг можно забить.
Но, эти варианты не подходитят.

Задача - разобраться что не нравится компилятору.

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

Если вместо TMac подставить int, то компилятор считает именно так, а вот с массивом он не понимает.


Ответить | Правка | ^ к родителю #3 | Наверх | Cообщить модератору

5. "Варнинг при -std=gnu99. Помогите разбраться."  +/
Сообщение от diff (??) on 01-Мрт-11, 11:13 
>[оверквотинг удален]
>> f((const TMac *)&mac);
> Да, тогда варнинга не будет. Еще можно убрать const в функции. Да
> и на варнинг можно забить.
> Но, эти варианты не подходитят.
> Задача - разобраться что не нравится компилятору.
> На мой взгляд все понятно - ф-ии передается указатель на неконстантный массив,
> но функция ждет указатель на константный массив и поэтому внутри ф-ии
> массив будет константным и его изменять нельзя.
> Если вместо TMac подставить int, то компилятор считает именно так, а вот
> с массивом он не понимает.

Очевидно компилятор обрабатывает встроенные типы (int,double) и пользовательские по разному

Ответить | Правка | ^ к родителю #4 | Наверх | Cообщить модератору

6. "Варнинг при -std=gnu99. Помогите разбраться."  +/
Сообщение от Nah email on 01-Мрт-11, 11:33 
> Очевидно компилятор обрабатывает встроенные типы (int,double) и пользовательские по разному

Звучит логично, но это не так.
Если в примере выше TMac определить как структуру, то все ОК.
Проблема именно с массивами (любыми массивами - интов, структур, указателей).

Есть ещё у кого-нибудь варианты :-)


Ответить | Правка | ^ к родителю #5 | Наверх | Cообщить модератору

7. "Варнинг при -std=gnu99. Помогите разбраться."  +/
Сообщение от diff (??) on 01-Мрт-11, 12:02 
>> Очевидно компилятор обрабатывает встроенные типы (int,double) и пользовательские по разному
> Звучит логично, но это не так.
> Если в примере выше TMac определить как структуру, то все ОК.
> Проблема именно с массивами (любыми массивами - интов, структур, указателей).
> Есть ещё у кого-нибудь варианты :-)

Т.к. массивы передаются по указателю, очевидно, что компилятор требует чтобы значения были константными. (В отличие от встроенных типов которые итак копируются на стек, т.е. изменению не подлежат)

Ответить | Правка | ^ к родителю #6 | Наверх | Cообщить модератору

8. "Варнинг при -std=gnu99. Помогите разбраться."  +/
Сообщение от gpl77 (ok) on 01-Мрт-11, 14:26 
>> Очевидно компилятор обрабатывает встроенные типы (int,double) и пользовательские по разному
> Звучит логично, но это не так.
> Если в примере выше TMac определить как структуру, то все ОК.
> Проблема именно с массивами (любыми массивами - интов, структур, указателей).
> Есть ещё у кого-нибудь варианты :-)

Вот так?
(Или я не понял что вы спрашиваете)

#include <stdio.h>
typedef unsigned char TMac[6];
void f(const TMac* mac)
{
    puts(mac?"mac":"no mac");
}
int main()
{
    /*const*/ TMac mac;
    f((const TMac *) &mac);
    return 0;
}

Ответить | Правка | ^ к родителю #6 | Наверх | Cообщить модератору

9. "Варнинг при -std=gnu99. Помогите разбраться."  +/
Сообщение от Nah email on 01-Мрт-11, 16:11 
> Вот так?
>  (Или я не понял что вы спрашиваете)

Не подходит. Вариант с приведением типов уже предлагали выше.

Проблема решилась.

Оказывается:

1) Mac mac; //mac равен &mac (ну и, конечно всё равно указателя на первый элемент)
    (операция & к имени массива не действует)

2) Компилятором трактуются по-разному "указатель на массив" и "указатель на указатель на элемент массива"
    void f(const TMac* mac);  НЕ то же самое что
    void f(const unsigned char** mac);

Т.о. в моем случае надо писать
void f(const TMac mac);
вместо
void f(const TMac* mac);

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

Здесь можно найти интересную информацию по теме.
http://stackoverflow.com/questions/1810083/c-pointers-pointi...

Здесь комментарий на эту тему от разработчика компилятора gcc.
http://gcc.gnu.org/ml/gcc-help/2009-12/msg00026.html

Всем спасибо ;-)

Ответить | Правка | ^ к родителю #8 | Наверх | Cообщить модератору

10. "Варнинг при -std=gnu99. Помогите разбраться."  +/
Сообщение от pavlinux (ok) on 03-Мрт-11, 01:13 
>> Вот так?
>>  (Или я не понял что вы спрашиваете)
> Не подходит. Вариант с приведением типов уже предлагали выше.
> Проблема решилась.
> Оказывается:

1.
        Большая часть путаницы вокруг указателей в С происходит от
        непонимания этого утверждения. "Эквивалентность" указателей и
        массивов не позволяет говорить не только об идентичности, но и
        взаимозаменяемости.

    "Эквивалентность" относится к следующему ключевому определению:

        значение типа массив-Т, которое появляется
        в выражении, превращается (за исключением трех случаев)    в
        указатель на первый элемент массива; тип результирующего
        указателя - указатель-на-Т.

    (Исключение составляют случаи, когда массив оказывается    операндом
        sizeof, оператора & или инициализатором символьной строки для
        массива литер.)

        Вследствие этого определения нет заметной разницы в поведении
        оператора индексирования [], если его применять к массивам и
        указателям. Согласно правилу, приведенному выше, в выражении типа
        а[i] ссылка на массив "a" превращается в указатель и дальнейшая
        индексация происходит так, как будто существует выражение с
        указателем p[i] (хотя доступ к памяти будет различным.  
        В любом случае выражение x[i], где х - массив или указатель)
        равно по определению *((x)+(i)).

        Смотри:  K&R I Разд.5.3 c.93-6; K&R II Разд.5.3 c. 99; H&S
        Разд.5.4.1 c. 93; ANSI  Разд.3.2.2.1, Разд.3.3.2.1,
        Разд.3.3.6 .

2:      Как объявить указатель на массив?

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

        Вместо указателя на массив рассмотрим использование указателя на один
        из элементов массива.  Массивы типа T превращаются в указатели типа Т
        (см. 1), что удобно; индексация или увеличение указателя
        позволяет иметь доступ к отдельным элементам массива. Истинные
        указатели на массивы при увеличении или индексации указывают на
        следующий массив и в общем случае если и полезны, то лишь при
        операциях с массивами массивов.

        Если действительно нужно объявить указатель на целый массив,
    используйте что-то вроде  "int (*ap)[N];" где N    - размер массива.
    Если размер массива неизвестен, параметр N может быть опущен, но
    получившийся в результате тип "    указатель на массив неизвестного
        размера" - бесполезен.

3.      Исходя из того, что ссылки на массив превращаются в указатели,
        скажите в чем разница для массива

    int array[NROWS][NCOLUMNS];

        между array и &array?

O:      Согласно ANSI/ISO стандарту C, &array дает указатель типа
        "указатель-на-массив-Т", на весь массив
        В языке C до выхода стандарта ANSI оператор & в &array игнорировался,
        порождая предупреждение компилятора. Все компиляторы C, встречая
        просто имя массива, порождают указатель типа указатель-на-Т, т.е. на
        первый элемент массива. (Cм. 1)

Ответить | Правка | ^ к родителю #9 | Наверх | Cообщить модератору

11. "Варнинг при -std=gnu99. Помогите разбраться."  +/
Сообщение от pavlinux (ok) on 03-Мрт-11, 01:42 
> Ещё раз, что же не нравится копилятору и как написать коректно?


#include <stdio.h>

typedef unsigned char (*TMac)[6]; /* ахтунг */

void f(const TMac * mac)
{
        puts(mac ? "mac" : "no mac");
}

int main()
{
        TMac mac;
        f(&mac);
        return 0;
}


Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру