Использование `(void *)` в качестве параметра функции вместо `struct *`

Есть ли большая разница, если я использую что-то вроде этого:

void print_struct( void *ptr_to_struct )

вместо:

void print_struct( struct data *ptr_to_struct )

Я спрашиваю об этом, потому что я просто застрял в чем-то, чего не могу понять, и почему это не работает следующим образом:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void print_struct( struct data *ptr_to_struct );
struct data{
    char name[ 256 ];
};

int main( void )
{
    struct data ptr;
    strcpy ( ptr.name, "George" );
    print_struct_1( &ptr);
}

void print_struct( struct data *ptr_to_struct )
{
    struct data *ptr = ptr_to_struct;
    printf("Name = %s\n", ptr->name );
}

Я получил:

error: ‘struct data’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror]

Но если я перееду:

void print_struct( struct data *ptr_to_struct );

После:

struct data{
    char name[ 256 ];
};

Компилируется нормально.

Я не понимаю следующего:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void print_struct( void *ptr_to_struct );
struct data{
    char name[ 256 ];
};
//void print_struct( void *ptr_to_struct );


int main( void )
{
    struct data ptr;
    strcpy ( ptr.name, "George" );
    print_struct_1( &ptr);
}

void print_struct( void *ptr_to_struct )
{
    struct data *ptr = ( struct data * )ptr_to_struct;
    printf("Name = %s\n", ptr->name );
}

Нет, если я использую:

void print_struct( void *ptr_to_struct );

До или после:

struct data{
    char name[ 256 ];
};

Программа работает нормально.

Почему такая разница?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
38
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  1. Когда вы ссылаетесь на неизвестный тип struct something в прототипе функции, он фактически объявляет новый тип структуры. Однако новый тип будет локальным для этого прототипа. Новый тип не будет связан с каким-либо типом struct something с одинаковыми именами, объявленным впоследствии. Например

    void foo(struct S *p) {}
    struct S { int i; };
    
    int main(void) {
      struct S s;
      foo(&s); // ERROR: the pointer types are unrelated
    }  
    

    В принципе, не делайте этого. Не используйте неизвестные типы struct something в прототипах функций. Бессмысленно. Практически всегда это указание на опечатку или другую ошибку. Вот почему компилятор выдает предупреждение.

    Такие типы структур должны быть объявлены прототипом до. Вы можете переставить свои объявления (как вы уже пробовали). Или вы можете предварительно объявить тип структуры

    struct data;
    void print_struct( struct data *ptr_to_struct );
    struct data{
      char name[ 256 ];
    };
    

    Это тоже будет работать правильно.

  2. Объявление прототипа функции с параметром типа void * и последующее определение той же функции с параметром типа struct something * приводит к неопределенному поведению, даже если ваша программа, похоже, "работает нормально".

Так что, если я использую его Как это нормально, или может привести к UB?

user10533142 20.11.2018 20:27

@Michael B .: То, что у вас есть по этой ссылке, выглядит нормально. Однако некоторые квалификаторы const совершенно необоснованны.

AnT 20.11.2018 20:43
Some const qualifiers are completely unjustified Почему? Я имею в виду, что цель состоит в том, чтобы сообщить компилятору, что я не касаюсь этого указателя или его указанного значения. Или я ошибаюсь?
user10533142 20.11.2018 20:48

@Michael B: Ну, в таком случае сделайте это последовательным: внутри вашего print_struct объявите ptr как const struct data *ptr. Это также сделает ненужным гипс. В настоящее время вы используете это приведение, чтобы отбросить некоторые из ваших const. Какой смысл использовать const, если вы все равно собираетесь сразу выбросить?

AnT 20.11.2018 20:59

Теперь я понимаю. Спасибо.

user10533142 20.11.2018 21:43

Другие вопросы по теме