Я только что переустановил Windows, чтобы Visual Studio не была установлена, и код был уродливым
using System;
using System.Diagnostics;
public static class test{
public static void Main(string[] args){
MyTest();
PowTest();
}
static void PowTest(){
var sw = Stopwatch.StartNew();
double res = 0;
for (int i = 0; i < 333333333; i++){
res = Math.Pow(i,30); //pow(i,30)
}
Console.WriteLine("Math.Pow: " + sw.ElapsedMilliseconds + " ms: " + res);
}
static void MyTest(){
var sw = Stopwatch.StartNew();
double res = 0;
for (int i = 0; i < 333333333; i++){
res = MyPow(i,30);
}
Console.WriteLine("MyPow: " + sw.ElapsedMilliseconds + " ms: " + res);
}
static double MyPow(double num, int exp)
{
double result = 1.0;
while (exp > 0)
{
if (exp % 2 == 1)
result *= num;
exp >>= 1;
num *= num;
}
return result;
}
}
Результаты:
csc / o test.cs
test. exe
MyPow: 6224 ms: 4.8569351667866E+255
Math.Pow: 43350 ms: 4.8569351667866E+255
Возведение в степень путем возведения в квадрат (см. https://stackoverflow.com/questions/101439/the-most-efficient-way-to-implement-an-integer-based-power- function-powint-int ) намного быстрее, чем Math.Pow в моем тесте (мой процессор - Pentium T3200 с частотой 2 ГГц)
РЕДАКТИРОВАТЬ: .NET версия 3.5 SP1, ОС Vista Vista SP1 и План питания - высокая производительность.
Gcc не помещает определение структуры где-либо во время выполнения. Это означает, что вы не можете этого сделать стандартно.
Это может зависеть от того, для чего вы используете информацию о типе. Двумя основными приложениями могут быть:
В первом случае часто доступна информация, хранящаяся в символах, выводимых компилятором и прикрепленная к исполняемому файлу (во многих среды).
Реализация зависит от платформы и часто означает, что компилятор должен быть проинструктирован для вывода этой информации. Один из примеров такой программы - gdb. Указатели все равно должны быть введены правильно, чтобы это было полезно.
Для сериализации типы часто помечаются значениями, как вы предлагаете. Эти теги не t хотя должны храниться вместе с данными в памяти. Их можно добавить с помощью процедуры вывода.
Вы не можете.
Указатель просто хранит адрес и ничего не имеет отношения к его содержимому.
«Я пытаюсь не указывать идентификаторы в своих структурах для определения их типа». Не избегайте этого. Если вы действительно хотите иметь возможность проверять тип, поместите typeID в качестве первого элемента каждой структуры. Твой порыв был неплохим.
Указатель - это тип. В более общем плане C не дает возможности заниматься самоанализом. Программного способа определения типа переменной нет.
Нет, нигде нет информации о типе времени выполнения.
Вы должны писать свои функции так, чтобы что сигнатура функции содержит информацию о типе и позволяет компилятору проверять типы статически. Например, void burp_foo (struct foo * thefoo)
сообщает, что аргумент является указателем на struct foo
. Заказчик должен предоставить его. Конечно, с помощью преобразования типов можно указать любой указатель, указывающий на struct foo
, но тогда это проблема вызывающего, а не ваша.
Вы не можете сделать это в C. На самом деле компилятор C ++ делает что-то вроде того, что вы хотите (сохраняя информацию о типе класса в выделенной памяти). В C нет классов, а есть только структуры, которые вообще не содержат служебных данных.
The C standard does not allow this directly. The C++ standard has some ability to do this (dynamic_cast
and typeid
).
typeof
GCC comes with a typeof operator that may be useful depending on what you're doing.
The conditional operator (the question mark and colon in expressions like x = y == 0 ? 1 : 0;
) has some ability to tell you if two types can be coerced into a third type (that article is about C++, but the type safety of the conditional operator is the same in C). Its use is nonobvious to say the least.
Both of these techniques (typeof
and the conditional operator) are limited to what information is available at compile time. That is, you can't pass a void*
to a function and then use typeof
to figure out the original type of the object the pointer points to inside that function (because such information isn't available inside that function at compile time).
Thinking more about this, GTK+ is written in C and has a system you may consider emulating. It looks like they use type IDs, but instead of putting the IDs in the struct, they use macros to look things up.
В C. Указатель имеет либо определенный тип, либо void *
. Нет перегрузки функций или встроенного полиморфизма времени выполнения, как в C ++. Однако вы можете выполнять псевдообъектно-ориентированные трюки, используя указатели на функции, например:
typedef void (*cmd_func)( int );
struct command
{
int arg;
cmd_func action;
};
Способ избежать использования Член ID в вашей структуре должен использовать полиморфизм, например:
typedef struct {
char const *name;
int id;
/* ... */
} object_info_t;
typedef struct {
object_info_t *info;
} object_t;
typedef struct {
object_t object;
int a;
} foo_t;
typedef struct {
object_t object;
int b;
} bar_t;
int object_get_id(object_t *object)
{
return object->info->id;
}
Обратите внимание, что вы можете дополнить object_info_t
указателями на функции и вообще не проверять id
s:
typedef struct {
char const *name;
int id;
int (*do_something)(object_t *);
} object_info_t;
int object_do_something(object_t *self)
{
return self->info->do_something(self);
}
Все ответы, размещенные здесь, говорят: «Вы не можете». Они правы. Вы не можете.
Но, и я не решаюсь даже упоминать об этом, есть игр, в которые можно играть. Эти игры - плохая идея. Я не рекомендую их ни в какой ситуации.
В чем игра? Вставка лишних битов данных в неиспользуемые части адреса и их удаление везде, где вы используете адрес.
Итак, представьте, что у вас есть указатели на структуру или класс размером 32 байта. Если вы убедитесь, что ваши выделения памяти выровнены по 32-байтовому адресу (что легко для динамических распределений, но сложнее гарантировать для стековых), все младшие биты адреса будут равны 0. Это означает, что есть 5 свободных битов в внизу адреса, достаточно поставить флажки, идентификационные номера, Даже если у вас нечетный размер структуры, практически любой компилятор C или C ++ и операционная система всегда будут выравнивать каждый адрес по 4 байта.
В 64-битных кодах вы обычно можете найти значительное количество свободных битов на верхнем конце адресов. .. очень вероятно, 16 свободных неиспользуемых битов ждут вас. Конечно, это зависит от ОС. А также плохая идея. Вам нравится опасность, не так ли?
Два недостатка:
(источник: ecoworldly.com )
Существует так много способов, которые могут привести к возникновению ошибок, сбоев и боли. Помните, как я сказал, что компиляторы выравнивают память как минимум по 4 байтам? Что ж, это правда. Пока вы не найдете новую ОС, которой нет. А ты - пища для тигров.
Так что не делай этого.
Но, тем не менее, это действительно способ вставить небольшую дополнительную информацию, такую как номер типа, в каждый адрес. Вы можете увидеть эту технику в коде посчитанного байта или в запутанном C.
PS: На самом деле, я серьезно, не делайте этого. Даже если вы любите тигров.