Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.02.2023, 19:37   #1
khpga
 
Регистрация: 21.02.2023
Сообщений: 8
Лампочка структуры в Си

Задан шаблон структурного типа:
Код:
struct student{
char *name;
char gender;
int year_of_birth;
char *spec;
int year;
char *group;
float average;
};
Написать функцию addr_diff(), возвращающую разницу адресов полей year и year_of_birth.

Для примера:

Результат
3
khpga вне форума Ответить с цитированием
Старый 22.02.2023, 04:31   #2
Пётр Седов
Форумчанин
 
Регистрация: 26.10.2022
Сообщений: 119
По умолчанию

Цитата:
Сообщение от khpga Посмотреть сообщение
Для примера:

Результат
3
Это на какой платформе получается 3?
Код:
#include <stdio.h>

struct student {
  char* name;
  char gender;
  int year_of_birth;
  char* spec;
  int year;
  char* group;
  float average;
};

typedef unsigned char byte_t;

int addr_diff(const struct student* s) {
  return (const byte_t*)&s->year - (const byte_t*)&s->year_of_birth;
}

int main() {
  struct student s;
  printf("pointer size: %i bytes\n", (int)sizeof(void*));
  printf("addr_diff = %i\n", addr_diff(&s));
  return 0;
}
Вывод на консоль:
Код:
pointer size: 4 bytes
addr_diff = 8
Пётр Седов вне форума Ответить с цитированием
Старый 22.02.2023, 06:42   #3
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 960
По умолчанию

Цитата:
Сообщение от khpga Посмотреть сообщение
шаблон структурного типа:
кто писал этот бред? Это не шаблон (а в Си вообще нет шаблонов, если что)
это - структура

подправленный вариант решения
Код:
#include <stdio.h>

typedef struct student
{
    char* name;
    char gender;
    int year_of_birth;
    char* spec;
    int year;
    char* group;
    float average;
}student;

size_t addr_diff(student* s)
{
    return (const char*)&s->year - (const char*)&s->year_of_birth;
}

int main()
{
    student s;
    printf("pointer size: %zu bytes\n", sizeof(void*));
    printf("addr_diff = %zu\n", addr_diff(&s));
    
    printf("%p\n", &s.year_of_birth);
    printf("%p\n", &s.year);
    
    return 0;
}
Код:
pointer size: 8 bytes
addr_diff = 12
0x7ffd9608e90cd
0x7ffd9608e918d
кстати, примечательно, что если 16-ю строку написать так
Код:
return &s->year - &s->year_of_birth;
, то результат 3
во втором случае - разница двух указателей на int , в штуках

Последний раз редактировалось BDA; 23.02.2023 в 05:04.
Алексей1153 вне форума Ответить с цитированием
Старый 23.02.2023, 04:02   #4
Пётр Седов
Форумчанин
 
Регистрация: 26.10.2022
Сообщений: 119
По умолчанию

Алексей1153, начинающим программистам лучше не связываться с типом size_t, потому что беззнаковая арифметика -- грабли:
https://programmersforum.ru/showthread.php?t=344535
Да и во «взрослых» программах тип size_t редко когда реально нужен.
Пётр Седов вне форума Ответить с цитированием
Старый 23.02.2023, 07:44   #5
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 960
По умолчанию

Пётр Седов, у них нет выбора, связываться или не связываться. Они им сразу пользуются, если используют массив или вектор. Использование int для размеров и индексов - это некорректно

при попытке вычитать size_t из size_t необходимо сначала их сравнить. Это придётся делать и в детских, и во взросных программах
Алексей1153 вне форума Ответить с цитированием
Старый 24.02.2023, 05:47   #6
Пётр Седов
Форумчанин
 
Регистрация: 26.10.2022
Сообщений: 119
По умолчанию

Цитата:
Сообщение от Алексей1153 Посмотреть сообщение
Пётр Седов, у них нет выбора, связываться или не связываться. Они им сразу пользуются, если используют массив или вектор.
Можно сразу приводить к int, чтобы не допустить расползание size_t по коду:
Цитата:
Сообщение от Пётр Седов Посмотреть сообщение
Код:
for (int i = 0; i < static_cast<int>(Visited.size()) - 1; i++) {
Цитата:
Сообщение от Алексей1153 Посмотреть сообщение
Использование int для размеров и индексов - это некорректно
Корректно даже unsigned char использовать, если не требуется > 255 элементов. В стандартной библиотеке повсеместно используется size_t просто потому, что стандартная библиотека обязана быть универсальной, на все платформы (16-, 32- и 64-битные). Но обычно не требуется работать с контейнерами у которых > 2 миллиарда элементов, а вот граблей хочется избежать, поэтому в некоторых серьёзных проектах индексы и количество элементов хранят в int. Например, в Doom 3:
https://github.com/id-Software/DOOM-...eo/idlib/Str.h
Цитата:
Сообщение от Str.h
Код:
...
class idStr {

public:
	...
	char				operator[]( int index ) const;
	char &				operator[]( int index );
	...
	int					Length( void ) const;
	...
protected:
	int					len;
	char *				data;
	int					alloced;
	char				baseBuffer[ STR_ALLOC_BASE ];
	...
};
...
https://github.com/id-Software/DOOM-...tainers/List.h
Цитата:
Сообщение от List.h
Код:
...
template< class type >
class idList {
public:
	...
	int				Num( void ) const;									// returns number of elements in list
	...
	const type &	operator[]( int index ) const;
	type &			operator[]( int index );
	...
private:
	int				num;
	int				size;
	int				granularity;
	type *			list;
};
...
Беззнаковая арифметика в C, C++ -- настолько частые грабли, что:
* Авторы Java вообще отказались от типов unsigned int, unsigned long.
* Авторы C++ добавили функцию std::ssize (signed size).
Пётр Седов вне форума Ответить с цитированием
Старый 24.02.2023, 08:51   #7
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 960
По умолчанию

Пётр Седов, не надо вводить новичков в заблуждение Есть тип size_t, им надо пользоваться.
Алексей1153 вне форума Ответить с цитированием
Старый 24.02.2023, 09:28   #8
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,709
По умолчанию

Цитата:
Сообщение от Пётр Седов Посмотреть сообщение
Можно сразу приводить к int, чтобы не допустить расползание size_t по коду:
И получить скрытые проблемы, т.к. это зависит от реализации.

Цитата:
Сообщение от Пётр Седов Посмотреть сообщение
Корректно даже unsigned char использовать, если не требуется > 255 элементов.
1. Только стоит учитывать, что вполне возможны доп. расходы на расширение/обнуление остальной части регистра.
2. Если использовать, то сразу обкладывать ассертами, чтобы сюрпризов не было.

Цитата:
Сообщение от Пётр Седов Посмотреть сообщение
поэтому в некоторых серьёзных проектах индексы и количество элементов хранят в int.
Ну-ну

Цитата:
Сообщение от Пётр Седов Посмотреть сообщение
Авторы C++ добавили функцию std::ssize (signed size).
А вы мотивационную часть по std::ssize читали?
p51x вне форума Ответить с цитированием
Старый 24.02.2023, 09:35   #9
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 960
По умолчанию

я ещё добавлю, что переполнение беззнаковой переменной - это нормальная ситуация с точки зрения языка. А переполнение знаковой переменой - это UB
Алексей1153 вне форума Ответить с цитированием
Старый 24.02.2023, 09:50   #10
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Цитата:
Сообщение от p51x Посмотреть сообщение
И получить скрытые проблемы, т.к. это зависит от реализации.
И что теперь, int, char и long тоже не юзать? Они ведь тоже зависят от реализации...
waleri вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Передача структуры из программы на c# в dll на c++ и получение структуры из dll iukash Общие вопросы .NET 0 07.05.2013 16:03
Динамические структуры данных, списковые структуры (надо разобраться что делает программа) _4Alex4_ Помощь студентам 1 14.11.2012 07:39
Написание программ (древовидные структуры, структуры неспециального вида и т.д.) Green Gin Фриланс 2 27.04.2012 15:26
Управляющие структуры. Программирование алгоритмов разветвляющейся структуры. Лёнка Компоненты Delphi 1 23.04.2012 15:03
структуры в С++ серг Общие вопросы C/C++ 2 13.12.2009 15:08