Каково поведение сравнения указателя на статическую переменную? - PullRequest
2 голосов
/ 07 апреля 2019

Я прочитал что-то вроде указателя, равны, если: они оба указывают на один и тот же адрес или одну и ту же функцию.

Работает ли это с static функцией, которые имеют одинаковые имена, но имеют разные адреса?

main.c :

#include <stdio.h>

extern void *p1;
extern void *p2;

int main() {
    printf("%d\n", p1 == p2);
    return 0;
}

А * :

static void f() {}

Bc :

#include "A.h"
void *p1 = &f;

Копия :

#include "A.h"
void *p2 = &f;

Что будет печатать этот код или это может быть неопределенное поведение?

Ответы [ 2 ]

3 голосов
/ 07 апреля 2019

Код будет иметь неопределенное поведение, но по той причине, что стандарт C не определяет, что произойдет, когда указатель на функцию преобразуется в указатель на void.

Преобразование конвертируемости указателя на функцию в указатель на void указано как общее расширение ( C11 J.5.7 ), и POSiX требует этого. Однако, вероятно, все же следует использовать явное приведение.


Два указателя на функцию будут сравниваться равными друг другу, только если они указывают на одну и ту же функцию ( C11 6.5.9p6 )

Два указателя сравнивают равные, если и только [...], оба являются указателями на один и тот же объект (включая указатель на объект и подобъект в его начале) или функцию, [...]

Две функции с внутренней связью в разных единицах перевода различны, поэтому указатели на них должны сравниваться не одинаково; и void * преобразование их аналогичным образом, если гарантируется обратное путешествие.


Я прочитал стандарт как таковой, что, если компоновщик объединяет два определения с идентичным кодом, реализация не соответствует. ( C11 6.2.2p2 )

0 голосов
/ 07 апреля 2019

В вашем коде есть 2 проблемы:

  • функция определена static в каждом модуле, компилятор создаст отдельный объект для каждого модуля, что может сделать компоновщик илиможет не объединяться, учитывая одинаковый код для обоих, независимо от их идентичного static имени.Однако такая оптимизация кажется несоответствующей, поэтому функции должны иметь другой адрес.

  • указатели имеют тип void *, что не гарантирует однозначного хранения указателя на функцию,Фактически, Стандарт C не определяет поведение преобразования указателя на функцию в указатель на тип объекта.Таким образом, если вы не предполагаете расширение стандарта C, поведение не определено.Вы должны определить p1 с типом void (*p1)(); и т. Д.

Скорее всего, программа выведет 0, но это поведение не гарантируется, пока вы не исправите проблему с типом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...