Как Вы проверяете, имеет ли указатель, в C, определенный тип?

Я только что переустановил 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 и План питания - высокая производительность.

13
задан unwind 5 June 2009 в 09:07
поделиться

10 ответов

Gcc не помещает определение структуры где-либо во время выполнения. Это означает, что вы не можете этого сделать стандартно.

Это может зависеть от того, для чего вы используете информацию о типе. Двумя основными приложениями могут быть:

  1. Отладка или аналогичная проверка во время выполнения
  2. Сериализация и десериализация структур данных

В первом случае часто доступна информация, хранящаяся в символах, выводимых компилятором и прикрепленная к исполняемому файлу (во многих среды).

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

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

9
ответ дан 1 December 2019 в 17:12
поделиться

Вы не можете.

Указатель просто хранит адрес и ничего не имеет отношения к его содержимому.

39
ответ дан 1 December 2019 в 17:12
поделиться

«Я пытаюсь не указывать идентификаторы в своих структурах для определения их типа». Не избегайте этого. Если вы действительно хотите иметь возможность проверять тип, поместите typeID в качестве первого элемента каждой структуры. Твой порыв был неплохим.

14
ответ дан 1 December 2019 в 17:12
поделиться

Указатель - это тип. В более общем плане C не дает возможности заниматься самоанализом. Программного способа определения типа переменной нет.

7
ответ дан 1 December 2019 в 17:12
поделиться

Нет, нигде нет информации о типе времени выполнения.

Вы должны писать свои функции так, чтобы что сигнатура функции содержит информацию о типе и позволяет компилятору проверять типы статически. Например, void burp_foo (struct foo * thefoo) сообщает, что аргумент является указателем на struct foo . Заказчик должен предоставить его. Конечно, с помощью преобразования типов можно указать любой указатель, указывающий на struct foo , но тогда это проблема вызывающего, а не ваша.

4
ответ дан 1 December 2019 в 17:12
поделиться

Вы не можете сделать это в C. На самом деле компилятор C ++ делает что-то вроде того, что вы хотите (сохраняя информацию о типе класса в выделенной памяти). В C нет классов, а есть только структуры, которые вообще не содержат служебных данных.

2
ответ дан 1 December 2019 в 17:12
поделиться

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.

conditional operator

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.

0
ответ дан 1 December 2019 в 17:12
поделиться

В C. Указатель имеет либо определенный тип, либо void * . Нет перегрузки функций или встроенного полиморфизма времени выполнения, как в C ++. Однако вы можете выполнять псевдообъектно-ориентированные трюки, используя указатели на функции, например:


typedef void (*cmd_func)( int );
struct command
{
    int      arg;
    cmd_func action;
};
1
ответ дан 1 December 2019 в 17:12
поделиться

Способ избежать использования Член 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);
}
2
ответ дан 1 December 2019 в 17:12
поделиться

Все ответы, размещенные здесь, говорят: «Вы не можете». Они правы. Вы не можете.

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

В чем игра? Вставка лишних битов данных в неиспользуемые части адреса и их удаление везде, где вы используете адрес.

Итак, представьте, что у вас есть указатели на структуру или класс размером 32 байта. Если вы убедитесь, что ваши выделения памяти выровнены по 32-байтовому адресу (что легко для динамических распределений, но сложнее гарантировать для стековых), все младшие биты адреса будут равны 0. Это означает, что есть 5 свободных битов в внизу адреса, достаточно поставить флажки, идентификационные номера, Даже если у вас нечетный размер структуры, практически любой компилятор C или C ++ и операционная система всегда будут выравнивать каждый адрес по 4 байта.

В 64-битных кодах вы обычно можете найти значительное количество свободных битов на верхнем конце адресов. .. очень вероятно, 16 свободных неиспользуемых битов ждут вас. Конечно, это зависит от ОС. А также плохая идея. Вам нравится опасность, не так ли?

Два недостатка:

  1. Вы должны обязательно замаскировать ценности прежде, чем вы попытаетесь разыменовать указатель или передать его ко всему, что может попробовать. Это делает уродливый код.
  2. Вы танцуете за краю непереносимость обрыва глупых опасности. Это как выпить бутылка текилы и ходьба протертый канат над голодными тиграми. Обнаженная.

Your fate if you follow my advice
(источник: ecoworldly.com )

Существует так много способов, которые могут привести к возникновению ошибок, сбоев и боли. Помните, как я сказал, что компиляторы выравнивают память как минимум по 4 байтам? Что ж, это правда. Пока вы не найдете новую ОС, которой нет. А ты - пища для тигров.

Так что не делай этого.

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

PS: На самом деле, я серьезно, не делайте этого. Даже если вы любите тигров.

6
ответ дан 1 December 2019 в 17:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: